12: Graphical-User Interfaces

What We Will Cover


Continuations

Homework Questions?

Questions from last class?

12.1: Introduction to Inheritance

Objectives

At the end of the lesson the student will be able to:

  • Describe how inheritance is used in Java
  • Inherit from Java's classes
  • Implement subclasses of a JFrame

12.1.1: Introducing Inheritance

Inheritance: the ability to define new classes from existing ones.

  • Inheritance is one of the important ideas of object-oriented programming
  • It lets you code a class that is based on another class
  • When used correctly, inheritance can simplify the overall design
  • As you will see, Java uses inheritance extensively in its API

How Inheritance Works

  • A class that inherits is called the subclass (derived, child)
  • A class that is inherited from is called the superclass (base, parent)
  • The subclass automatically contains all the variable and method definitions of the superclass
  • In a subclass, you define new fields and methods not found in the superclass
  • The two classes in the following diagram show how this works
  • Here the superclass is a JFrame in the javax.swing package
  • You use a JFrame to create a GUI window, which is called a frame
  • The class has several public constants and methods used to set-up the JFrame
  • For instance, setSize() lets you set the width and height of a JFrame
  • In the HelloFrame subclass you can use all the constants and methods inherited from JFrame
  • In addition, the example has added constants and a constructor method
  • These new constants and methods are specific to the HelloFrame subclass

About the Diagram

  • The first rectangular section of a class diagram contains the class name
  • The second section describes the attributes (data variables)
  • The third (bottom) section describes the operations (methods)
  • A minus sign (-) marks attributes and operations that cannot be accessed by other classes
  • Plus sign (+) marks attributes and operations that can be accessed by other classes
  • Parameters are listed in parenthesis separated by commas
  • The upward pointing arrow indicates inheritance

12.1.2: Inheritance Example

  • Deriving a new class from an existing one requires the extends clause
  • Syntax:
  • public class SubclassName extends SuperclassName
  • A subclass can only extend one superclass
  • The following code implements the HelloFrame subclass described in the previous section
  • Note how little new code is needed to create a HelloFrame
  • Most of the program statements are contained in the JFrame superclass

Example Subclass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import javax.swing.*;

public class HelloFrame extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;

    public static void main(String[] args) {
        new HelloFrame();
    }

    public HelloFrame() {
        super("Hello Frame Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }
}

Using super()

  • Note the call to super() in the above example
  • You can use super() to call the constructor of the superclass
  • If you call super() with no arguments, then you call the no-parameter constructor
  • Calling super() with a String argument, like in the example, calls the constructor of the superclass that accepts a String parameter
  • Calling super() is optional
  • Java automatically calls super() with no arguments if you do not code something else
  • If you do call super() then it must be first statement in a constructor definition

12.1.3: Class Hierarchies

  • Classes can be derived from derived classes
    • Subclass objects can be treated as superclass objects
    • Child classes can be parent classes
  • Classes higher in the hierarchy are called ancestor classes
  • Classes lower in the hierarchy are called descendent classes
  • A class can use the variables and methods of any of its superclasses
  • For example, a Frame uses the variables and methods provided by both Window and Container
  • Note that inheritance describes an is-a relationship
    • A Dialog is a Window
  • This is in contrast to the has-a relationship when a class contains another class

Diagram Showing an Inheritance Hierarchy

  • Following is taken from the Java API
  • Shows that a superclass can have more than one subclass
  • For instance, Window has two subclasses

Another Way to Draw Inheritance

  • There are many ways to draw inheritance diagrams
  • Following is another way to show the inheritance hierarchy for Container
  • Note how the superclass is always drawn higher than the subclass
  • Container
       |
       +--Panel
       |     |
       |     +--Applet
       |
       +--Window
             |
             +--Frame
             |
             +--Dialog
    
    

12.1.4: Creating JFrames

  • A JFrame is a window designed for GUI applications
  • It inherits many methods from both the Frame and Window class
  • To code a GUI application, you typically extend JFrame
  • public class HelloWindow extends JFrame
  • When you close a JFrame, you usually want to exit your application
  • To make this happen you can use the method setDefaultCloseOperation()
  • setDefaultCloseOperation(EXIT_ON_CLOSE);
  • By default, all frames are 0 x 0 pixels and open in the top left corner of the screen
  • To set both the size and location you can use the setBounds() method
  • setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
  • Another way is to call the methods setLocation() and setSize()
  • Note that component sizes and locations are expressed in pixels
  • Also, the screen starts in the top left corner

  • JFrames are invisible when first created to give you a chance to make adjustments
  • When you are done setting up the frame, you need to call the setVisible() method
  • setVisible(true);
  • The following example shows how to set up a minimal JFrame

Example Code for a Minimal JFrame

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import javax.swing.*;

public class HelloFrame extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;

    public static void main(String[] args) {
        new HelloFrame();
    }

    public HelloFrame() {
        super("Hello Frame Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }
}

Commonly Used Methods of the Frame Class

Method Description
setTitle(StringObj) Sets the title bar to the specified string.
setResizable(booleanValue) Sets whether or not this frame can be resized.

Commonly Used Methods of the Window Class

Method Description
pack() Size this window to fit the preferred size and layout of its components.
setBounds(intX, intY, intWidth, intHeight) Sets the location and size of this component.

Commonly Used Methods of the Component Class

Method Description
getHeight() Returns the height of the component as an int.
getWidth() Returns the width of the component as an int.
getX() Returns the x coordinate of the components as an int.
getY() Returns the y coordinate of the components as an int.
setLocation(intX, intY) Moves this component to a new (x, y) location.
setSize(intWidth, intHeight) Resizes this component to a new width and height.
setVisible(booleanValue) Shows or hides this component depending on the value of the argument.

12.1.5: Summary

  • You can use inheritance to create a subclass (derived, child)
  • A subclass inherits fields and methods from a superclass (base, parent)
  • Inheritance allows you to develop hierarchies of classes like those in the Java API
  • Subclasses can directly use the variables and methods of all the its superclasses
  • Deriving a new class from an existing one requires the extends clause
  • public class HelloFrame extends JFrame
  • You can define new variables and methods in a subclass
  • Also, you can call constructors of the superclass using the super() method
  • super("Hello Frame Application");
    
  • Most Java GUI applications inherit from a JFrame
  • By extending a JFrame, you can use all the variables and methods of JFrame and its ancestors

Exercise 12.1

In this exercise we explore how to create a minimal JFrame.

Specifications

  1. Save the following code file as HelloFrame.java.
  2. Compile and run the code to look at its various features.
  3. Change the call to the super() method to display a different title.
  4. Change the size and start location of the JFrame
  5. Add code to call the setResizable() method and set it to make your HelloFrame unresizable.
  6. Submit your modified program as the answer for this exercise.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import javax.swing.*;

public class HelloFrame extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;

    public static void main(String[] args) {
        new HelloFrame();
    }

    public HelloFrame() {
        super("Hello Frame Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }
}

12.2: Introduction to Graphical User Interfaces

Objectives

At the end of the lesson the student will be able to:

  • Describe what is meant by a graphical-user interface
  • Describe what is meant by a component
  • List the three categories of GUI components
  • Code a JPanel and add it to a JFrame
  • Code a JButton and add it to a JPanel

12.2.1: About Graphical User Interfaces (GUIs)

  • Graphical User Interface (GUI) -- pronounced "gooey"
    • Graphical: not just text or characters but includes windows, menus, buttons, etc.
    • User: person using the program via mouse, keyboard, etc.
    • Interface: interaction with the program using visual controls, widgets, etc.
  • Most modern programs use a GUI
  • Typical graphical elements include:
    • Window: portion of screen that serves as a smaller screen within the screen
    • Menu: list of alternatives offered to user
    • Button: looks like a button that can be pressed
  • Objects that make up a GUI are called components
  • Java provides two sets of components: AWT and Swing
  • AWT (Abstract Window Toolkit) is the older set of components
    • Relies on the underlying visual components of the operating system
    • GUIs look different on each operating system
  • Swing (like the dance) is the newer set of components
    • Draws its own visual components on the screen
    • Originates from AWT components
    • Adds new capabilities
  • We will use Swing components

Example GUI

GUI Programming Tip

  • When you create GUIs, you usually create all the buttons and other components
  • Once you create the look of your application, then you add the functionality for each component
  • We will use this same approach to learn about GUI programming
  • In these sections we look at how to create visual components in JFrame
  • Later we will look at how to make the program take an action when a component is used

12.2.2: GUI Components

  • Java has two special libraries for implementing GUI interfaces: AWT and Swing
  • AWT was the original library that shipped with Java 1.0
  • Swing was added in Java 2 (SDK 1.2) in the package javax.swing
  • You can easily identify Swing components because their names start with "J"
  • Swing classes inherit from AWT classes, extending their capabilities
  • The component hierarchy is:

12.2.3: Component Categories

  • Component: a visual object that responds to user actions
  • Container: an object that holds other objects
  • GUI components fall into three categories
    1. Top-Level Containers
    2. Intermediate Containers
    3. Control Components
  • We now examine components in each category

Top-Level Containers

  • These are basic window structure that ties the GUI into the operating system
  • They include capabilities such as borders and resizability
  • They hold both intermediate containers and control components
  • Every GUI program must have one top-level container
  • Some of the frequently used components are:
  • Component Description
    JFrame A top-level window with a title, border and buttons for closing, maximizing/restoring and iconifying the window.
    JApplet Container for applets, which are small programs that run inside a Web browser
    JOptionPane Limited window that makes it easy to pop up a standard dialog box that prompts users for a value or informs them of something.

Intermediate Containers

  • These are objects added to a top-level container
  • They can hold other intermediate containers and control components
  • They are used to organize placement of control components
  • Some of the frequently used components are:
  • Component Description
    JPanel Provides a general-purpose container for control components and other intermediate containers.
    JRootPane A container used behind the scenes by JFrame, JApplet and other containers.
    JScrollPane A container that provides a scrollable view of a component.

Control Components

  • These are graphical objects used to accept input or display information
  • They must be placed in a container object using the add() method
  • Some of the frequently used controls are:
  • Component Description
    JButton Display area that triggers an event when clicked.
    JComboBox Drop-down list of items from which the user can make a selection by clicking an item in the list or possibly by typing into a box.
    JCheckBox GUI component that can be selected or deselected and displays its state to the user as a checked square.
    JRadioButton GUI component that can be selected or deselected and displays its state to the user as a filled or unfilled circle.
    JLabel Display area for text or icons
    JTextField Single-line display and input area for the user to enter data from the keyboard.
    JTextArea Multi-line display and input area for the user to enter data from the keyboard.

Further Information

12.2.4: Adding a Panel to a Frame

  • In section 12.1.4 we looked at how to create frames using a JFrame
  • After you create a frame, you need to add components to it
  • One component you often add is an intermediate container named JPanel
  • You use a JPanel to contain control components and other intermediate containers
  • A JFrame has a special component it uses to store other components called the content pane
  • In older versions of Java, the procedure for adding components was took three steps
  • JPanel panel = new JPanel();
    Container contentPane = getContentPane();
    contentPane.add(panel);
    
  • Since JDK1.5 you can add a JPanel to the content pane of a JFrame using:
  • JPanel panel = new JPanel();
    add(panel);
    
  • You could add controls components, such as buttons, directly to the content pane
  • However, you often add components to a panel and then add the panel to the content pane
  • This helps you to group components so your code is easier to read and understand

Methods to Add Components to the Content Pane

Method Description
getContentPane() Returns the content pane as a Container object.
add(componentObj) Adds a component object to this container.

12.2.5: Adding Buttons to a Panel

  • Button: a component the user clicks to trigger a specific action
  • Basic buttons are created with class JButton
  • You can add a button to a panel like this:
  • JPanel panel = new JPanel();
    JButton button = new JButton("Hello");
    panel.add(button);
    
  • The first two statements create the panel and the button
  • The third statement adds the button to the panel
  • The following example adds two buttons to a panel and then adds the panel to a frame

Example With a JPanel and JButton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.awt.*;
import javax.swing.*;

public class HelloFrame2 extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;
    private JButton helloButton;
    private JButton exitButton;

    public static void main(String[] args) {
        new HelloFrame2();
    }

    public HelloFrame2() {
        super("Hello Frame Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        helloButton = new JButton("Hello");
        exitButton = new JButton("Exit");
        JPanel panel = new JPanel();
        panel.add(helloButton);
        panel.add(exitButton);
        add(panel);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }
}

Commonly Used Constructors of the JButton Class

Constructor Description
JButton() Creates a button without any text or icons.
JButton(StringObj) Creates a button displaying the specified text.
JButton(IconObj) Creates a button displaying the specified icon.
JButton(StringObj, IconObj) Creates a button displaying both the specified string and icon.

Some Methods of the JButton Class (and Ancestors)

Method Description
getText() Returns the text of this button as a String.
setText(StringObj) Sets the text of this button.
setEnabled(booleanValue) Enables the button if the argument is true; otherwise it disables the button.
setEnabled(booleanValue) Enables the button if the argument is true; otherwise it disables the button.

12.2.6: Summary

  • Java provides special libraries for implementing GUI interfaces, the newer of which is called Swing
  • GUI components fall into three categories:
    • Top-level containers: basic window structure that ties the GUI into the operating system
    • Intermediate containers: used to hold other components
    • Control components: graphical objects used to accept input or display information
  • To add components to a JFrame, you often use a JPanel
  • To add button components, you use the JButton class
  • You add a button using code like:
  • JPanel panel = new JPanel();
    helloButton = new JButton("Hello");
    panel.add(helloButton);
    add(panel);
    

Exercise 12.2

In this exercise we explore how to add buttons to a JFrame.

Specifications

  1. Save the following code file as HelloFrame2.java.
  2. Compile and run the code to look at its various features.
  3. Add another JButton to the code.
  4. Submit your modified program as the answer for this exercise.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.awt.*;
import javax.swing.*;

public class HelloFrame2 extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;
    private JButton helloButton;
    private JButton exitButton;

    public static void main(String[] args) {
        new HelloFrame2();
    }

    public HelloFrame2() {
        super("Hello Frame Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        helloButton = new JButton("Hello");
        exitButton = new JButton("Exit");
        JPanel panel = new JPanel();
        panel.add(helloButton);
        panel.add(exitButton);
        add(panel);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }
}

12.3: Interfaces and Event Handling

Objectives

At the end of the lesson the student will be able to:

  • Describe what is meant by event-driven programming
  • Code classes that implement interfaces
  • Handle button events by implementing interfaces

12.3.1: Event-Driven Programming

  • Programs with GUIs use what is known as Event-Driven Programming
  • A program waits for "events" to occur and then responds
  • Examples of events include:
    • Clicking a mouse button
    • Dragging the mouse
    • Pressing a key on the keyboard

Terminology

  • Firing an event: when an object generates an event
  • Listener: object that waits for events to occur
  • Event handler: method that responds to an event

Traditional "Uneventful" Programming vs. Event-Driven Programming

"Uneventful" Event Driven
Which action is taken next determined by the computer Which action taken next determined by the user
Program starts in main and ends after the last statement completes Program starts in main but ends when the user says to end
Programs are lists of instructions performed in order with some branching Programs are objects that can fire events and objects that react to events
Program performed by one agent -- the computer Program is interaction between user and computer

12.3.2: Handling Events Using Interfaces

  • To handle events, Java uses a special kind of code structure known as an interface
  • An interface is like a class in some ways, but very limited
  • An interface defines a set of public methods that can be implemented by a class
  • The interface itself does not provide any code to implement the methods
  • Instead, it just provides the method headings
  • A class that implements an interface must provide an implementation for each method defined by the interface
  • One other thing that an interface can provides is static constants
  • These constants are available to any class that implements the interface
  • The following are some of the interfaces provided for event handling

Some Interfaces for Event Handling

Interface Description
ActionListener Used to listen for ActionEvents that occur on many GUI components like a JButton.
MouseListener Used to listen for "interesting" MouseEvents such as button clicks.
WindowListener Used to listens for WindowEvents that occur during a window's life.

12.3.3: Implementing Interfaces

  • Any class can choose to implement zero or more interfaces
  • Syntax:
  • public class ClassName [extends SuperClass]
        [implements Interface1 [, Interface2]...] { }
    
  • Classes implementing an interface add the keyword implements in the
  • class header
  • After the implements keyword, you code a comma-delimited list of interface names
  • class HelloListener implements ActionListener
    
  • A class that implements an interface must implement all methods of the interface
  • For instance, the ActionListener interface has one method that must be implemented:
  • public void actionPerformed(ActionEvent ae) { }
    

Interface Arguments

  • A method can have an interface parameter
  • A method that accepts an interface as an argument can accept any object implementing that interface
  • The accepting method can in turn call the implemented method
  • The Java API has several methods that accept interface arguments
  • For instance, the JButton has a method that accepts an ActionListener
  • public void addActionListener(ActionListener l);
  • This means that you can pass it an object of any class that implements the ActionListener interface
  • Then the JButton knows that it can call the actionPerformed() method defined in the object

12.3.4: Responding to Button Clicks

  • So far the buttons do not respond when the user clicks them
  • To make them respond, we need to listen to the button for user clicks
  • Whenever a user clicks a JButton, it generates an ActionEvent object
  • Any object that registers with the JButton receives the ActionEvent object
  • The JButton sends the ActionEvent by calling the actionPerformed() method
  • public void actionPerformed(ActionEvent ae)
  • Inside the actionPerformed() method we need to write code that responds to the event
    • This is known as event-handling code
  • The following only shows how to handle an ActionEvent
  • However, you use the same principles to handle other types of events

How to Listen for and Handle an ActionEvent

  1. Define a class that implements the ActionListener interface
  2. class HelloListener implements ActionListener
    
  3. Implement the ActionListener interface by coding an actionPerformed() method in the class
  4. public void actionPerformed(ActionEvent ae) {
        System.out.println("Hey");
    }
    
  5. Register the ActionListener object with the object you want to listen to by calling the addActionListener() method
  6. helloButton.addActionListener(new HelloListener());
    

Example Implementing an ActionListener Event Handler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class HelloFrame3 extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;
    private JButton helloButton;
    private JButton exitButton;

    public static void main(String[] args) {
        new HelloFrame3();
    }

    public HelloFrame3() {
        super("Hello Frame Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        helloButton = new JButton("Hello");
        helloButton.addActionListener(new HelloListener());
        exitButton = new JButton("Exit");
        exitButton.addActionListener(new ExitListener());
        JPanel panel = new JPanel();
        panel.add(helloButton);
        panel.add(exitButton);
        add(panel);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }
}

class HelloListener implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
        System.out.println("Hey");
    }
}

class ExitListener implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
        System.out.println("Goodbye!");
        System.exit(0);
    }
}

12.3.5: Using Inner Classes for Event Handlers

  • A convenient way to organize event handlers is to use an inner class
  • An inner class is a class that is contained within the curly-braces of another class
  • Syntax:
  • public class OuterClass {
        // code for outer class
        class InnerClass {
            // code for inner class
        }
    }
    
  • An inner class has access to all members of its containing class
  • This makes inner classes an easy and flexible way to implement event listeners

Example Showing the Need for an Inner Class

  • For example, let us add an on-off button to our HelloFrame example
  • JButton onOffButton;
  • We initialize the button with the label "On"
  • onOffButton = new JButton("On");
  • When the button is pressed, we want the label to change to "Off"
  • To add this behavior, we can write an event handler:
  • class OnOffListener implements ActionListener {
        public void actionPerformed(ActionEvent ae) {
            if (onOffButton.getText().equals("On")) {
                onOffButton.setText("Off");
            } else {
                onOffButton.setText("On");
            }
        }
    }
    
  • And finally, we register the event handler with the onOffButton
  • onOffButton.addActionListener(new OnOffListener());
    
  • The complete code that implements the on-off button is shown below
  • Note that if we had implemented the OnOffListener class as a separate top-level class, the code would not compile
  • HelloFrame4.java:52: cannot find symbol
    symbol  : variable onOffButton
    location: class OnOffListener
                if (onOffButton.getText().equals("On")) {
                    ^
    
  • The reason is that the onOffButton is defined in another class
  • By making the OnOffListener an inner class, the event handler has access to the variables and methods of the outer class
  • There are other ways to provide access to the frame class, but his is one of the easiest and most flexible techniques
  • Thus, you would do well to make all the event handlers an inner class as shown in the following example

Example Implementing an ActionEvent as an Inner Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class HelloFrame4 extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;
    private JButton helloButton;
    private JButton exitButton;
    private JButton onOffButton;

    public static void main(String[] args) {
        new HelloFrame4();
    }

    public HelloFrame4() {
        super("Hello Frame Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        helloButton = new JButton("Hello");
        helloButton.addActionListener(new HelloListener());
        exitButton = new JButton("Exit");
        exitButton.addActionListener(new ExitListener());
        onOffButton = new JButton("On");
        onOffButton.addActionListener(new OnOffListener());
        JPanel panel = new JPanel();
        panel.add(helloButton);
        panel.add(exitButton);
        panel.add(onOffButton);
        add(panel);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }

    class HelloListener implements ActionListener {
        public void actionPerformed(ActionEvent ae) {
            System.out.println("Hey");
        }
    }

    class ExitListener implements ActionListener {
        public void actionPerformed(ActionEvent ae) {
            System.out.println("Goodbye!");
            System.exit(0);
        }
    }

    class OnOffListener implements ActionListener {
        public void actionPerformed(ActionEvent ae) {
            if (onOffButton.getText().equals("On")) {
                onOffButton.setText("Off");
            } else {
                onOffButton.setText("On");
            }
        }
    }
}

12.3.6: Summary

  • Graphical user interfaces use a type of programming known as event-driven programming
  • Programs wait for the user to create an event and then responds
  • To handle events, Java uses a special kind of code structure known as an interface
  • An interface can contain:
    • Public static constants
    • Method declarations
  • Any class can choose to implement zero or more interfaces
  • class HelloListener implements ActionListener
  • A class that implements an interface must implement all methods of the interface
  • public void actionPerformed(ActionEvent ae) { }
  • To make a button respond when clicked, you add an ActionEvent handler
  • There are three steps for adding an ActionEvent handler:
  1. Define a class that implements the ActionListener interface
  2. class HelloListener implements ActionListener
    
  3. Implement the ActionListener interface by coding an actionPerformed() method in the class
  4. public void actionPerformed(ActionEvent ae) {
        System.out.println("Hey");
    }
    
  5. Register the ActionListener object with the object you want to listen to by calling the addActionListener() method
  6. helloButton.addActionListener(new HelloListener());
    
  • To make your coding easier, you should implement event listeners as inner classes

Check Yourself

  1. Why do you need to register an object as a listener
  2. What method does a control component call when it generates an ActionEvent?
  3. Where do you place the code that responds to an ActionEvent?
  4. Why is an inner class a convenient way to implement event listener classes?

Exercise 12.3

In this exercise we explore how to handle events for buttons.

Specifications

  1. Save the following code file as HelloFrame3.java.
  2. Compile and run the code to check how it handles button clicks.
  3. Add another JButton to the code.
  4. Add an event handler for the new button.
  5. Submit your modified program as the answer for this exercise.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class HelloFrame3 extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;
    private JButton helloButton;
    private JButton exitButton;

    public static void main(String[] args) {
        new HelloFrame3();
    }

    public HelloFrame3() {
        super("Hello Frame Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        helloButton = new JButton("Hello");
        helloButton.addActionListener(new HelloListener());
        exitButton = new JButton("Exit");
        exitButton.addActionListener(new ExitListener());
        JPanel panel = new JPanel();
        panel.add(helloButton);
        panel.add(exitButton);
        add(panel);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }
}

class HelloListener implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
        System.out.println("Hey");
    }
}

class ExitListener implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
        System.out.println("Goodbye!");
        System.exit(0);
    }
}

12.4: Laying Out Components

Objectives

At the end of the lesson the student will be able to:

  • Describe the purpose of a layout manager
  • Use the FlowLayout Manager
  • Use the BorderLayout Manager
  • Describe how to organize layout code

12.4.1: About Layout Managers

  • When you add multiple components to a GUI, your program has to set the size and position of each component.
  • You use a layout manager to provide this functionality
  • Each Container object has a default layout manager
  • For instance, a JPanel uses a FlowLayout manager
  • On the other hand, content panes like those used in JFrame use a BorderLayout manager
  • Normally, you only need to think about layout managers when:
    • You add components to a container
    • You do not like the default layout manager
  • To add a new layout manager, you use the setLayout() method of the container
  • We will discuss two commonly used layout managers in the next few sections

Method of the Container Class Used to Change Layout Managers

Method Description
setLayout(LayoutManagerObj) Sets the layout manager for this container.

12.4.2: Using the FlowLayout Manager

  • The FlowLayout manager is the default for a JPanel
  • It adds components to the top of a container moving from left to right
  • When a container runs out of horizontal space, it starts adding components to a new row
  • You can adjust the alignment of the components on a row using the alignment fields of the FlowLayout class:
    • FlowLayout.CENTER
    • FlowLayout.LEFT
    • FlowLayout.RIGHT

For Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.awt.*;
import javax.swing.*;

public class FlowLayoutApp extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;
    private JButton button1;
    private JButton button2;
    private JButton button3;
    private JButton button4;
    private JButton button5;

    public FlowLayoutApp() {
        super("Flow Layout Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        button1 = new JButton("Button One");
        button2 = new JButton("Button Two");
        button3 = new JButton("Button with a long name");
        button4 = new JButton("Button Four");
        button5 = new JButton("5");

        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout(FlowLayout.LEFT));
        panel.add(button1);
        panel.add(button2);
        panel.add(button3);
        panel.add(button4);
        panel.add(button5);
        add(panel);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }

    public static void main(String[] args) {
        new FlowLayoutApp();
    }
}

Commonly Used Constructors of the FlowLayout Class

Constructor Description
FlowLayout() Constructs a new FlowLayout with a centered alignment.
FlowLayout(intAlign) Constructs a new FlowLayout with the specified alignment.

More Information

12.4.3: Using the BorderLayout Manager

  • You can align buttons left or right with a FlowLayout manager
  • However, you cannot place buttons at the bottom of the container
  • To do that, you use the BorderLayout manager
  • With a BorderLayout manager, you can place components in 5 separate regions
  • To create a new BorderLayout, you typically call its no-arg constructor:
  • BorderLayout bl = new BorderLayout()
    
  • To add the BorderLayout to a container you use the setLayout() method
  • panel.setLayout(new BorderLayout());
    
  • The default layout manager of a content pane is BorderLayout
  • To add a component to a container using a BorderLayout, you specify:
  • add(ComponentObj, regionField);
  • If you do not specify the region, the component is added to the center region

For Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.awt.*;
import javax.swing.*;

public class BorderLayoutApp extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;
    private JButton button1;
    private JButton button2;
    private JButton button3;
    private JButton button4;
    private JButton button5;

    public BorderLayoutApp() {
        super("BorderLayout Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        button1 = new JButton("North");
        button2 = new JButton("South");
        button3 = new JButton("East");
        button4 = new JButton("West");
        button5 = new JButton("Center");

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(button1, BorderLayout.NORTH);
        panel.add(button2, BorderLayout.SOUTH);
        panel.add(button3, BorderLayout.EAST);
        panel.add(button4, BorderLayout.WEST);
        panel.add(button5, BorderLayout.CENTER);
        add(panel);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }

    public static void main(String[] args) {
        new BorderLayoutApp();
    }
}

Commonly Used Constructors of the BorderLayout Class

Constructor Description
BorderLayout() Constructs a new BorderLayout.

More Information

12.4.4: Combining Layout Managers

  • The FlowLayout manager lets you align components left, center or right
  • However, it does not let you place components at the bottom of the container
  • On the other hand, the BorderLayout manager lets you put components at the bottom
  • However, you can only place one component at the bottom
  • To get multiple components at the bottom of a window, you must combine layout managers
  • Since you can only have one layout manager per container, you must have multiple containers to get the effect of multiple layouts
  • The following code shows how you add two layouts together
  • The first container is named firstPanel and uses a BorderLayout
  • buttonNorth = new JButton("North");
    buttonEast = new JButton("East");
    buttonWest = new JButton("West");
    buttonCenter = new JButton("Center");
    
    JPanel firstPanel = new JPanel();
    firstPanel.setLayout(new BorderLayout());
    firstPanel.add(buttonNorth, BorderLayout.NORTH);
    firstPanel.add(buttonEast, BorderLayout.EAST);
    firstPanel.add(buttonWest, BorderLayout.WEST);
    firstPanel.add(buttonCenter, BorderLayout.CENTER);
    
  • The second container is named secondPanel and uses a FlowLayout
  • buttonSouth1 = new JButton("South 1");
    buttonSouth2 = new JButton("South 2");
    JPanel secondPanel = new JPanel();
    secondPanel.setLayout(
        new FlowLayout(FlowLayout.RIGHT));
    secondPanel.add(buttonSouth1);
    secondPanel.add(buttonSouth2);
    
  • We then add the secondPanel to the firstPanel
  • firstPanel.add(secondPanel, BorderLayout.SOUTH);
    
  • Thus you combine layouts by nesting them inside another container
  • The complete code is shown below

For Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.awt.*;
import javax.swing.*;

public class CombinedLayoutApp extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 150;
    private JButton buttonNorth;
    private JButton buttonEast;
    private JButton buttonWest;
    private JButton buttonCenter;
    private JButton buttonSouth1;
    private JButton buttonSouth2;

    public CombinedLayoutApp() {
        super("Combined Layout Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        buttonNorth = new JButton("North");
        buttonEast = new JButton("East");
        buttonWest = new JButton("West");
        buttonCenter = new JButton("Center");

        JPanel firstPanel = new JPanel();
        firstPanel.setLayout(new BorderLayout());
        firstPanel.add(buttonNorth, BorderLayout.NORTH);
        firstPanel.add(buttonEast, BorderLayout.EAST);
        firstPanel.add(buttonWest, BorderLayout.WEST);
        firstPanel.add(buttonCenter, BorderLayout.CENTER);

        buttonSouth1 = new JButton("South 1");
        buttonSouth2 = new JButton("South 2");
        JPanel secondPanel = new JPanel();
        secondPanel.setLayout(
            new FlowLayout(FlowLayout.RIGHT));
        secondPanel.add(buttonSouth1);
        secondPanel.add(buttonSouth2);
        firstPanel.add(secondPanel, BorderLayout.SOUTH);
        add(firstPanel);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }

    public static void main(String[] args) {
        new CombinedLayoutApp();
    }
}

12.4.5: Other Layout Managers

Java provides other layout managers you can research and use including:

  • BoxLayout: positions components in a single row or column
  • CardLayout: lets you create an area that can contain different components at different times
  • GridBagLayout: places components in a grid and allows some components to span more than one cell
  • GridLayout: displays components with equal size in a row-column layout like a spreadsheet
  • SpringLayout: allows you to specify precise relationships between the edges of components

More Information

12.4.6: Absolute Positioning

  • It is possible to do without a layout manager and use absolute positioning
  • However, you should use a layout manager if at all possible
  • Not using a layout manager restricts the user interface and usually makes a substandard interface
  • To show the components optimally, you often need to make the frame a fixed size and not resizeable
  • A fixed-size frame can interfere with other applications the user is running
  • To get a feel for these limitations, run the following example

Example of Absolute Positioning

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.awt.*;
import javax.swing.*;

public class AbsoluteApp extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 300, HEIGHT = 170;
    private JButton button1;
    private JButton button2;
    private JButton button3;
    private JButton button4;
    private JButton button5;

    public AbsoluteApp() {
        super("Absolute Positioning Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        button1 = new JButton("Button One");
        button2 = new JButton("Button Two");
        button3 = new JButton("Button with a long name");
        button4 = new JButton("Button Four");
        button5 = new JButton("5");

        button1.setBounds(10, 10, 100, 50);
        button2.setBounds(120, 10, 100, 50);
        button3.setBounds(230, 10, 150, 50);
        button4.setBounds(10, 70, 100, 50);
        button5.setBounds(120, 70, 50, 50);

        JPanel panel = new JPanel();
        panel.setLayout(null);
        panel.add(button1);
        panel.add(button2);
        panel.add(button3);
        panel.add(button4);
        panel.add(button5);
        add(panel);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }

    public static void main(String[] args) {
        new AbsoluteApp();
    }
}
  • To remove the layout manager, you set the layout to null
  • panel.setLayout(null);
    
  • Now you need to set the position and size of each component individually
  • button1.setBounds(10, 10, 100, 50);
    

More Information

12.4.7: Summary

  • When you add multiple components to a GUI, your program has to set the size and position of each component
  • You use a layout manager to provide this functionality
  • Normally, you only need to think about layout managers when:
    • You add components to a container
    • You do not like the default layout manager
  • To set a new layout for a container, you use the setLayout() method
  • To set a new FlowLayout for a panel, you code something like:
  • panel.setLayout(new FlowLayout(FlowLayout.LEFT));
    
  • To set a new BorderLayout for a panel, you code something like:
  • panel.setLayout(new BorderLayout());
    
  • To add a component to a container using a BorderLayout, you code something like:
  • panel.add(button1, BorderLayout.NORTH);
    
  • If you do not specify the region, the component is added to the center region
  • You can combine layout managers using multiple containers
    • One container is added to another container
    firstPanel.add(secondPanel, BorderLayout.SOUTH);
    
  • Java has other layout managers you can use
  • Also, you can remove the layout manager and set all the component positions and sizes individually
  • However, you produce more professional and user friendly applications by using a layout manager

Exercise 12.4

In this exercise we explore how to combine layout managers.

Specifications

  1. Compile and run the BorderLayoutExer.java code shown below.
  2. Revise the code so that the buttons are displayed in a row like this:
  3. Submit your updated code along with these exercises
import java.awt.*;
import javax.swing.*;

public class BorderLayoutExer extends JFrame {
    public final static int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 450, HEIGHT = 150;
    private JButton button1;
    private JButton button2;
    private JButton button3;
    private JButton button4;
    private JButton button5;

    public BorderLayoutExer() {
        super("BorderLayout Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        button1 = new JButton("Button 1");
        button2 = new JButton("Button 2");
        button3 = new JButton("Button 3");
        button4 = new JButton("Button 4");
        button5 = new JButton("Button 5");

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(button1, BorderLayout.NORTH);
        panel.add(button2, BorderLayout.SOUTH);
        panel.add(button3, BorderLayout.EAST);
        panel.add(button4, BorderLayout.WEST);
        panel.add(button5, BorderLayout.CENTER);
        add(panel, BorderLayout.CENTER);

        setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        setVisible(true);
    }

    public static void main(String[] args) {
        new BorderLayoutExer();
    }
}

One possible answer.

Wrap Up

Home | WebCT | Announcements | Schedule | Expectations | Course info
Help | FAQ's | HowTo's | Links

Last Updated: November 19 2005 @15:18:33