Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

Introduction to Graphical User Interfaces (GUI)

Java Programming, Lecture Notes # 17, Revised 10/03/99.

Preface
Introduction
The "Hello World" GUI Program
Interesting Code Fragments
Program Listing

Preface

Students in Prof. Baldwin's Introductory Java Programming classes at ACC are not responsible for knowing and understanding the material in this lesson.  Rather, this material is presented simply as a preview of what is to come for those students. However, students in Prof. Baldwin's Intermediate Java Programming classes and Advanced Java Programming classes are responsible for knowing and understanding the material in this lesson.

Upgraded to JDK 1.2 on 12/16/98.

Introduction

This lesson provides a very brief introduction to the programming of a Graphical User Interface (GUI) often pronounced "gooey."

As a practical matter, most Java programs use a GUI for communication between the program and the user.  Many books on Java programming jump right into the development of such interfaces without providing adequate background instruction because, quite frankly, programming GUIs is more fun than programing the more mundane stuff that is necessary to learn Java programming fundamentals.

My teaching philosophy is that the student needs to have a firm grip on many important Java programming concepts before taking the step into GUI programming.

Therefore, in hopes of stemming the student's desire to skip over the fundamentals, I am going to provide this lesson for illustration purposes where I will show and discuss the mechanics of creating a GUI.  I will discuss the GUI at a relatively high level of programming knowledge, so don't be disappointed if you don't understand the discussion at this point.  Stick with me and you will gain that understanding as we progress through Java programming one step at a time.

If you really do understand the discussion of this program, you probably don't need to be enrolled in the Introductory Java Programming class.  The level of your knowledge is well beyond the introductory stage.

After this, we will cover many more lessons before returning to the important topics surrounding GUI programming

The "Hello World" GUI Program

The purpose of this program is to illustrate some of the code in a relatively simple Graphical User Interface.

Note that this program uses Swing components.  Therefore, the Swing class library must be installed and accessible to the compiler before you will be able to compile and run this program.  As of the original date of this writing (5/7/98), Swing 1.0.1 was freely available for downloading from the JavaSoft site.

This program begins with a heavyweight Frame object on the screen.  The Frame contains five components:
 

  1. A heavyweight Button with the caption "Toggle Color"
  2. A lightweight JButton with the caption "Say Hello"
  3. A lightweight JButton with the caption "Say Goodbye"
  4. A green heavyweight Label with an initial caption of   "Color Me".  This is the output or display component for the   program.
  5. A red heavyweight Label with the caption "Toggle Color".   This Label functions as a counterfeit Button object.

The lightweight components exhibit the JavaSoft metal look and feel.  The heavyweight components exhibit the look and feel of the underlying operating system.

If you click the heavyweight Button object, the background color of the display toggles between yellow and green. If you click the heavyweight Label object with the "Toggle Color" caption, a mouse listener on this component creates a counterfeit ActionEvent object and posts it to the system event queue, and blames it on the heavyweight Button object.  When the event emerges from the queue, the system thinks that someone has clicked the actual Button object and it toggles the background color of the display just as though the Button object had been clicked.

The heavyweight Label that serves as a counterfeit Button has no knowledge of the outcome.  All it knows is that it creates a counterfeit ActionEvent object and posts it to the event queue with the Button specified as the source of the event.

If you click either of the two lightweight buttons, the caption in the display changes to either "Hello" or "Goodbye" depending on which lightweight button you click.

Note that the controlling class for this program implements the ActionListener interface and therefore, an object of this class can serve as an action listener registered on its own components.  This leads to a compact, but somewhat cryptic programming style.

The program was tested using JDK 1.1.6 and Swing 1.0.1 under Win95. It was also tested using JDK 1.2 under Win95.
 

Interesting Code Fragments

This section highlights a number of code fragments that are important to your understanding of Java programming in order for you to be prepared to deal with GUIs.
 
The first fragment shows the requirement to import the required packages (or use an alternative, but longer programming style).
 

import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;//JDK 1.1 version
//import javax.swing.*;//JDK 1.2 version

 
The next fragment shows the beginning of the controlling class, which in this case implements the ActionListener interface.  Because it implements this interface, an object of this class can serve as a listener for action events on components contained in the object.
 
The fragment also declares two reference variables as instance variables that are used later in the program. (Later you will learn the difference between instance variables and class variables.) One of the instance variables is used by the action event handler to toggle the color of the display between yellow and green.

The other instance variable is a reference to a Label object that serves as the output or display component for the program.
 

public class Gui01 extends Frame implements ActionListener{
  boolean toggle = false;
  Label display;

 
All Java applications require a main() method.  The main method for this program is shown in the next fragment.  In this case, the method is short.  All it does is instantiate the object of this type that will serve as a listener on several of the components.
 

  public static void main(String[] args){
    Gui01 displayWindow = new Gui01();
  }//end main

 
The constructor for this class, as shown in the next several fragments, is pretty long.  Therefore, we will break it up and discuss it as several different fragments.
 
The next fragment shows the beginning of the constructor along with the invocation of two different property set methods to set the title of the Frame object and the layout of the object.  The layout establishes how GUI components are placed inside the Frame. FlowLayout places the components left-to-right, top-to-bottom.
 

  public Gui01(){//constructor
    setTitle("Copyright 1998, R.G.Baldwin");
    setLayout(new FlowLayout());//set layout for container

 
Following this, we instantiate and set properties on several of the components of the GUI.  In doing this, we invoke the parameterized constructors for the objects and also invoke some of the property set methods of the objects. Note in particular the use of the static symbolic constants of the Color class such as Color.green.  Additional comments regarding the instantiation of these components are provided in the full listing of the program that appears later in this lesson.
 

    Button toggleColorButton = new Button("Toggle Color");
    display = new Label("Color Me");
    display.setBackground(Color.green);
    Label toggleColorLabel = new Label("Toggle Color");
    toggleColorLabel.setBackground(Color.red); 
    JButton sayHelloButton = new JButton("Say Hello");
    JButton sayGoodbyeButton = new JButton("Say Goodbye");

 
The next fragment adds the components instantiated above to the Frame object according to the position specifications of the layout manager specified earlier.
 

    this.add(toggleColorButton);
    this.add(display);
    this.add(toggleColorLabel);
    this.add(sayHelloButton);
    this.add(sayGoodbyeButton);

 
Finally, we establish the size of the Frame object in pixels and make it visible.  At this point, we have a completely non-functional graphical user interface.  If the program were left in this condition, the GUI would appear on the screen, but it wouldn't do anything.  It would be necessary to abort the program (ctrl-c) to force it to terminate.
 

    setSize(300,150);//Set frame size 
    setVisible(true);//Display the frame

 
To make our user interface functional, we must develop an event handling design and create listener objects containing event handlers which implement the behavior required by that design.
 
We begin by registering a mouse listener object on the Label object that will behave as a counterfeit Button.  The behavior of the mouse listener event handler when a mouseClicked event occurs on the Label will be to generate a counterfeit action event and "blame" it on the Button object.  We will see how that is accomplished when we examine the code for the MouseListener class that we will define later in the program.

Note that in this case, we are registering an anonymous object of an external top-level class named MyMouseListener on the Label.  We pass a reference to the Button object to the constructor for this anonymous object.
 

    toggleColorLabel.addMouseListener(
                  new MyMouseListener(toggleColorButton));

 
Next we register this object as an action listener on the heavyweight Button object and the two lightweight JButton objects.  Recall again that it is possible to register this object as an action listener because this class implements the ActionListener interface.
 

    toggleColorButton.addActionListener(this);
    sayHelloButton.addActionListener(this);
    sayGoodbyeButton.addActionListener(this);

 
The single statement that follows in the next fragment instantiates an anonymous inner class object of type WindowAdapter, and  registers it for handling a windowClosing event on the Frame object.  This code uses the abbreviated syntax which defines the listener class anonymously (the  listener class does not have a class name and the object instantiated from the class does not have a name). The behavior of this listener object causes the program to terminate when the window is closed.
 
This is the last statement in the constructor for this object.
 

    this.addWindowListener(
         new WindowAdapter(){//anonymous class definition
           public void windowClosing(WindowEvent e){
             System.exit(0);//terminate the program
           }//end windowClosing()
         }//end WindowAdapter
       );//end addWindowListener

  }//end constructor

 
This next fragment is the actionPerformed method for this object. This method is invoked whenever one of the buttons is clicked, or a counterfeit action event is posted with the Button object as the specified source object. The code in this method causes the color of the  display to toggle between yellow and green or causes it to display Hello or Goodbye, depending upon which component is clicked.

The logic is fairly straightforward.  The code determines the source of the event by extracting the action command from the ActionEvent object passed in as a parameter and uses the source identification to decide what to do to the display.

This is the end of the controlling class named Gui01.
 

  public void actionPerformed(ActionEvent e){
    if(e.getActionCommand().equals("Toggle Color")){ 
      if(!toggle){
        toggle = true;
        display.setBackground(Color.yellow);
      }else{
        toggle = false;
        display.setBackground(Color.green);
      }//end else
    }else 
      if(e.getActionCommand().equals("Say Hello"))
        display.setText("Hello");
      else display.setText("Goodbye");
  }//end actionPerformed()
  //-----------------------------------------------------//
 
}//end class Gui01

 
The next fragment shows the external top-level class that is used to monitor for mouse clicks on a Label object.

Whenever the user clicks on the Label, the code in an object of this class creates a counterfeit ActionEvent object and posts it to the SystemEventQueue.

The source of the event is specified to be a Button object that is passed in when an object of this class is instantiated. Thus, the Label object "claims" to be the Button object and posts ActionEvent objects that are interpreted by the runtime system as originating at the Button object.

The type of ActionEvent generated is an ACTION_PERFORMED event. You will see where this information is used when instantiating the ActionEvent object for posting to the system event queue.

The posted events are automatically delivered to the actionPerformed() method of an ActionListener object registered on the Button.
 
Note that this class definition does not implement the MouseListener interface.  Rather, it extends the MouseAdapter class.

The class definition includes an overridden mouseClicked() method that is declared in the MouseListener interface and defined as an empty method in the MouseAdapter class.

This method contains one long and fairly complex statement that I won't attempt to explain at this point.  It is fully explained in the lesson that discusses the posting of events to the system event queue.
 

class MyMouseListener extends MouseAdapter{
  Button toggleColorButton;//reference to the Button

  MyMouseListener(Button toggleColorButton){//constructor
    this.toggleColorButton = toggleColorButton;
  }//end constructor
 
  //Overridden mouseClicked() method
  public void mouseClicked(MouseEvent e){
    //Note that the following is a single statement
    Toolkit.getDefaultToolkit().
        getSystemEventQueue().
        postEvent(new ActionEvent(toggleColorButton,
                                  ActionEvent.
                                  ACTION_PERFORMED,
                                  "Toggle Color"));
  }//end overridden mouseClicked() method
}//end MyMouseListener

 
So there you have it.  The actual code required to implement a relatively simple GUI with three buttons and two labels where four of the five components are capable of multicasting events.
 

Program Listing

A complete listing of the program with extensive comments is provided in this section.
 

/*File Gui01.java Copyright 1998, R.G.Baldwin

The purpose of this program is to illustrate some of the
code in a relatively simple Graphical User Interface.

Note that this program uses Swing components.  Therefore, 
the Swing class library must be installed and accessible
to the compiler.

This program begins with a heavyweight Frame object on the
screen.  The Frame contains five components:

A heavyweight Button with the caption "Toggle Color"
A lightweight JButton with the caption "Say Hello"
A lightweight JButton with the caption "Say Goodbye"
A green heavyweight Label with an initial caption of
  "Color Me".  This is the output component for the
  program.
A red heavyweight label with the caption "Toggle Color".
  This Label functions as a counterfeit Button object.
  
The lightweight components exhibit the JavaSoft metal
look and feel.  The heavyweight components exhibit the
look and feel of the underlying operating system.

If you click the heavyweight Button object, the background
color of the display toggles between yellow and green.
If you click the heavyweight Label object with the "Toggle
Color" caption, a mouse listener on this component creates
a counterfeit ActionEvent object and posts it to the 
system event queue, attributed to the heavyweight Button
object.  When it emerges from the queue, the system thinks
that someone clicked the actual Button object and toggles
the background color of the display just as though the 
Button object had been clicked.

If you click either of the two lightweight buttons, the
caption in the display changes to either "Hello" or
"Goodbye" depending on which lightweight button was
clicked.

Note that the controlling class implements
the ActionListener interface and therefore, an object of
this class can serve as an action listener registered
on its own components.  This leads to a compact, but 
somewhat cryptic programming style.

The program was tested using JDK 1.1.6 and Swing 1.0.1
under Win95.
*********************************************************/
//Import required packages
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;//JDK 1.1 version
//import javax.swing.*;//JDK 1.2 version

//=======================================================

public class Gui01 extends Frame implements ActionListener{
  //Instance variables required to respond to the
  // action event on the Button object.
  boolean toggle = false;
  
  //Instance variable used as the output display.
  Label display;
  
  //All applications have a main method
  public static void main(String[] args){
    //Instantiate and object of this type
    Gui01 displayWindow = new Gui01();
  }//end main
  //-----------------------------------------------------

  public Gui01(){//constructor
    //Invoke property methods to set the title and the
    // layout for the outer object of type Frame.
    setTitle("Copyright 1998, R.G.Baldwin");
    setLayout(new FlowLayout());//set layout for container
    
    //Instantiate a new object of type Button
    Button toggleColorButton = new Button("Toggle Color");
    
    //Instantiate the display as an object of type Label
    // and initialize its color to green using a static
    // constant of the Color class.
    display = new Label("Color Me");
    display.setBackground(Color.green);
    
    //Instantiate a Label object that will be used as a
    // fake button to generate counterfeit action events
    // and attribute them to the Button object.  Color
    // it red.
    Label toggleColorLabel = new Label("Toggle Color");
    toggleColorLabel.setBackground(Color.red);  
    
    //Instantiate two lightweight buttons of the Swing
    // class JButton that will be used to cause the words
    // Hello and Goodbye to be displayed in the display.
    // Note the different appearance of these buttons as
    // compared to the Button object instantiated above.
    JButton sayHelloButton = new JButton("Say Hello");
    JButton sayGoodbyeButton = new JButton("Say Goodbye");

    //Add all of the components to the Frame object
    this.add(toggleColorButton);
    this.add(display);
    this.add(toggleColorLabel);
    this.add(sayHelloButton);
    this.add(sayGoodbyeButton);

    setSize(300,150);//Set frame size    
    setVisible(true);//Display the frame

    //Register listener objects.
    
    //First register a mouse listener on the Label object.
    // The behavior of this event handler when a mouse
    // event occurs on the label will be to generate a
    // counterfeit action event and attribute it to the
    // Button object.
    toggleColorLabel.addMouseListener(
                  new MyMouseListener(toggleColorButton));
                    
    //Register this object as a listener object on the
    // Button object as well as on the two JButton 
    // lightweight button objects.
    toggleColorButton.addActionListener(this);
    sayHelloButton.addActionListener(this);
    sayGoodbyeButton.addActionListener(this);
    
    //The statement which follows instantiates anonymous
    // inner class object of type WindowAdapter, and 
    // registers it for handling a windowClosing event on
    // Frame object. This code uses the abbreviated syntax
    // which defines the listener class anonymously (the 
    // listener class does not have a class name and the
    // object instantiated from the class does not have
    // a name).The behavior of this listener object causes
    // the program to terminate when the window is closed.
    this.addWindowListener(
         new WindowAdapter(){//anonymous class definition
           public void windowClosing(WindowEvent e){
             System.exit(0);//terminate the program
           }//end windowClosing()
         }//end WindowAdapter
       );//end addWindowListener
  }//end constructor
  //-----------------------------------------------------//
   
  //This is the actionPerformed method for this object.
  // This method is invoked whenever one of the buttons
  // is clicked, or a counterfeit action event is posted
  // with the Button object as the specified source object.
  // The code in this method causes the color of the 
  // display to toggle between yellow and green or causes
  // it to display Hello or Goodbye, depending upon which
  // component is clicked.
  
  public void actionPerformed(ActionEvent e){
    if(e.getActionCommand().equals("Toggle Color")){  
      if(!toggle){
        toggle = true;
        display.setBackground(Color.yellow);
      }else{
        toggle = false;
        display.setBackground(Color.green);
      }//end else

    }else 
      if(e.getActionCommand().equals("Say Hello"))
        display.setText("Hello");
      else display.setText("Goodbye");
  }//end actionPerformed()
  //-----------------------------------------------------//
   
}//end class Gui01
//=========================================================

/*This top level class is used to monitor for mouse 
clicks on a Label object.  Whenever the user clicks on the 
label, the code in an object of this class creates a 
counterfeit ActionEvent object and posts it to the 
SystemEventQueue.  The source of the event is specified to 
be a particular Button object that is passed in when an 
object of this class is instantiated.  Thus, the Label 
object "claims" to be the Button object and posts 
ActionEvent objects that are interpreted by the runtime 
system as originating at the Button object.  The type of
ActionEvents generated are ACTION_PERFORMED events.  The 
events are automatically delivered to the actionPerformed()
method of an ActionListener object registered on the 
Button. */

class MyMouseListener extends MouseAdapter{
  Button toggleColorButton;//reference to the Button
  //-----------------------------------------------------//

  MyMouseListener(Button toggleColorButton){//constructor
    //Save reference to Button  
    this.toggleColorButton = toggleColorButton;
  }//end constructor
  //-----------------------------------------------------//
  
  //This is an overridden mouseClicked() method that is
  // declared in the MouseListener interface and defined
  // as an empty method in the MouseAdapter class.
  public void mouseClicked(MouseEvent e){
    //Note that the following is a single statement
    Toolkit.getDefaultToolkit().
        getSystemEventQueue().
        postEvent(new ActionEvent(toggleColorButton,
                                  ActionEvent.
                                  ACTION_PERFORMED,
                                  "Toggle Color"));
  }//end overridden mouseClicked() method
}//end MyMouseListener
//=======================================================//

-end-