CM10135 / Programming II:   Lecture 12


Intro to Graphical User Interfaces


I. House Keeping

  1. Why did I ask for class variables / methods for assignment one when they are well known to be evil?
    1. Because I want to know that you know the difference between class variables and instance variables.
    2. Because I wanted to make certain no one created hashes in every instance.
    3. Because I wanted to reduce the chance that you downloaded the solution from somewhere.
    4. Don't forget Prog 1 -- how to write good code.  Prog 2 -- how programming really works. Looking under the hood!
    5. If you didn't use class/instance variables, the documentation had better explain:
      1. Why not (with a very good reason)
      2. That you understand how you could have.
  2. Next coursework due Thursday 25 March, will probably release it today.
    1. You won't be able to do all of it until after next week's lectures.
    2. You won't be able to do much of it until after this week's lectures!
    3. That's why it's due on a Thursday.
  3. More on synchronization:
    1. If you use the synchronize(object) {...} structure, it doesn't stop everything from getting at that object, it only prevents anything from using synchronized methods or code blocks within that object.
    2. Notes have been corrected to make this clearer.
    3. You'll learn a lot more about locking next year in your databases course. 
    4. For this year, just need a vague notion about why it's useful & how it's done.
  4. The IDE I use is eclipse, this is now linked from the bottom of the course page.
    1. This is just in case your curious, you don't need to use it.
    2. Is apparently dead trendy though.
  5. Have ordered some books for you guys
    1. Books only cover GUIs, threads, events, applets, networking (hard book), basic programming (easy book).
    2. Books don't cover algorithms, complexity, data structures.
    3. Books:
      1. easier: Java Programming Today, Barbara Johnston.
      2. harder: Learning Java (O'Reilly, tiger mum & cubs) Niemeyer & Knudsen.
      3. May also want to look at Object-Oriented Programming with Java by David Barnes (the guy who wrote the Blue Jay book.)  It has nice networking examples too.
    4. Will be in shop next week, library soon I hope.

II. GUI: Graphical User Interface

  1. Most languages now have a way to build window applications.
  2. Even older languages like basic & lisp.
  3. One of the main reasons people use Java is because it provides good window widgets which are also platform independent.
    1. There are now other very good ways to do this, e.g. python.
    2. We'll talk more about the whole platform-independent thing & Java's history on Thursday, in the applets lecture.
  4. There are two main types of windowing widgets in Java, AWT & Swing.
    1. Most people use Swing now, so that's what we'll cover in this lecture.
    2. AWT was the original though, & you'll notice some things still come from its classes.
    3. Again, more on AWT Thursday.
  5. Modern windowing systems have many things in common:
    1. Basic widgets: buttons, menus, sliders.
    2. Certain organizational things: frames, windows, containers, panels.
    3. Once you've learned about these things, you'll see them in all the applications you use.
    4. Once you've learned the concepts, it's pretty easy to learn to do it in other languages.
  6. Languages or libraries for languages will often have some special widgets too.
  7. If you want something that you've seen in another language, you can often find it for any popular language via an Internet search.

III. Basic Ontologies

  1. Old standard:  Model, View, Controller.
    1. Model is essentially the underlying data & functionality.  What do you have and what can it do?
    2. View is the way it looks on the screen.  You might have different views for different people:
      1. different windowing systems,
      2. different preferences, `skins'.
      3. different permissions / options level
        1. e.g. Novice vs. Advanced options on browser
        2. all the same options are there in the code / model, but which ones you get check boxes for depend on how much you want to know, how much complexity you want to deal with.
        3. Can be used for security, e.g. should a customer see / know about options only a service provider can set?
    3. Controller is how you connect these two together:
      1. e.g. what happens when you mouse over a button?  when you push it?
      2. something needs to generate an event, and something needs to respond to that event.
  2. In Java, you must inherit from / extend a class that is essentially the main window, and implement a Listener.
    1. Widgets are also classes, instances of them become members of your new class.
    2. Listeners are for "listening for" events that occur in a program.
      1. Very much like catching an unforced exception.
      2. Can always ignore events, but users will be annoyed!
      3. Can do the listening with an anonymous inner class instead of a full implementation.
        1. Remember we talked about these in lecture 10.
        2. Demonstrated further below.

IV. Code Example

  1. Notes for the lecture:
    1. Write on board with  big spaces for the  inner class version.
    2. Only write the code, explain the comments.
    3. Just mention the imports, don't list.
  2. Here's the code...

    import java.awt.Container;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;

    /**
    * @author joanna
    *
    * Window demo, taken from Johnston04 (java prog today)
    *
    */
    public class BangPopAp extends JFrame implements ActionListener {

    // these are all the widgets our inane ap will use
    JButton bangButton = new JButton ("Bang");
    JButton popButton = new JButton ("Pop");

    // now we set everything up in the constructor...
    public BangPopAp() {
    // set the title bar for the window
    this.setTitle("Bangs and Pops!");

    // Frames come with their main container. This just adds a reference
    // so we can refer to it more easily.
    Container canvas = getContentPane();
    // the layout determines where things will go when we add them.
    canvas.setLayout (new GridLayout(2,1));

    // here we add the buttons
    canvas.add(bangButton);
    canvas.add(popButton);

    // we have to tell the buttons what's going to listen to them.
    // Doing this is sometimes called "registering". We can use the instance
    // `this' because we are implementing an ActionListener (see below).
    // Once we've registered, when an event happens to one of the buttons,
    // it will call its listener's .actionPerformed.
    bangButton.addActionListener(this); // Leave lots of space around these for inner classes!!
    popButton.addActionListener(this);

    // The below two methods are both inherited from JFrame.
    // The first sets the size the window will be when it appears.
    // Generally want a value so all your widgets look reasonable from start.
    this.setSize(250,150);
    // Everything would pretty much work now, but if we didn't do show()
    // no one could see it!
    this.show();

    }

    // this is the one thing we have to do to implement ActionListener.
    // We have to define method "actionPerformed". This just looks to see which
    // widget called it (buttons only have one action!)
    public void actionPerformed(ActionEvent e) {
    if (e.getSource()==bangButton) {
    JOptionPane.showMessageDialog(this, "Bang!");
    } else if (e.getSource()== popButton) {
    JOptionPane.showMessageDialog(this, "Pop!");
    }
    }

    // now all we do to start the ball rolling is make an instance...
    public static void main(String[] args) {
    BangPopAp theApp = new BangPopAp();
    // except we also need to say what to do when the frame is closed!
    // if we didn't have this line, the program would keep running even
    // after the window was gone (that would be bad...)
    theApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }


    } // class

  3. Thursday morning I'll tell you about a bunch of different possible widgets & layouts.
  4. There are a lot less options to replace JFrame with
    1. Applets (Thursday PM)
    2. JWindow
      1. simpler superclass of JFrame
      2. pretty much only used for splash screens.
  5. This lecture I'll tell you about more different listeners.
  6. But first, let's have a look at what we have to change to do this with inner classes:
    import java.awt.Container;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;

    /**
    * @author joanna
    *
    * GUI w/ inner classes demo, taken from Johnston04 (java prog today)
    *
    */
    public class BangPopInnerAp extends JFrame { // implements ActionListener {

    // these are all the widgets our inane ap will use
    JButton bangButton = new JButton ("Bang");
    JButton popButton = new JButton ("Pop");

    // now we set everything up in the constructor...
    public BangPopInnerAp() {
    // set the title bar for the window
    this.setTitle("Bangs and Pops!");

    // Frames come with their main container. This just adds a reference
    // so we can refer to it more easily.
    Container canvas = getContentPane();
    // the layout determines where things will go when we add them.
    canvas.setLayout (new GridLayout(2,1));

    // here we add the buttons
    canvas.add(bangButton);
    canvas.add(popButton);

    //Here's where the inner classes come in -- we can't use `this' anymore.
    // since we aren't extending the listener.
    bangButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent event) {
    JOptionPane.showMessageDialog(null, "Bang!");
    }
    });

    popButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent event) {
    JOptionPane.showMessageDialog(null, "Pop!");
    }
    });


    // The below two methods are both inherited from JFrame.
    // The first sets the size the window will be when it appears.
    // Generally want a value so all your widgets look reasonable from start.
    this.setSize(250,150);
    // Everything would pretty much work now, but if we didn't do show()
    // no one could see it!
    this.show();

    }

    /* this goes away now we're using inner classes
    public void actionPerformed(ActionEvent e) {
    if (e.getSource()==bangButton) {
    JOptionPane.showMessageDialog(this, "Bang!");
    } else if (e.getSource()== popButton) {
    JOptionPane.showMessageDialog(this, "Pop!");
    }
    }
    */
    // now all we do to start the ball rolling is make an instance...
    public static void main(String[] args) {
    BangPopAp theApp = new BangPopAp();
    // except we also need to say what to do when the frame is closed!
    // if we didn't have this line, the program would keep running even
    // after the window was gone (that would be bad...)
    theApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }


    } // class

  7. Duplicates some code for each widget, but,
    1. Eliminates need for logic in the actionPerformed method to determine which object got called,
    2. Localizes a little better --- code pertaining to widget objects less spread out.
  8. Remember, you can implement multiple interfaces, may want more than one kind of listener!

VI. Listeners

  1. ActionListener -- actionPerformed (button press, slider moved, etc)
  2. FocusListener -- focusGained (FocusEvent e), focusLost.
    1. Focus is basically where you can type, as in "focus of attention".
    2. You can also make a widget request the focus (like Google does in its search window) JComponent.requestFocus()
  3. MouseListener (MouseEvent e)
  4.  void mouseClicked(MouseEvent e)
              Invoked when the mouse button has been clicked (pressed and released) on a component.
     void mouseEntered(MouseEvent e)
              Invoked when the mouse enters a component.
     void mouseExited(MouseEvent e)
              Invoked when the mouse exits a component.
     void mousePressed(MouseEvent e)
              Invoked when a mouse button has been pressed on a component.
     void mouseReleased(MouseEvent e)
              Invoked when a mouse button has been released on a component.
    1. MouseMotionListener
       void mouseDragged(MouseEvent e)
                Invoked when a mouse button is pressed on a component and then dragged.
       void mouseMoved(MouseEvent e)
                Invoked when the mouse cursor has been moved onto a component but no buttons have been pushed.
  5. Also table, menu & hyperlink listeners, many others.

VI. Summary

  1. Introduced GUIs
  2. You should play with them & look at the documentation.

page author: Joanna Bryson
8 March 2004