9. More GUI Topics and Exceptions

What We Will Cover


Illuminations

Questions on Completed Assignments?

9.1: Menus

Objectives

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

  • Write code that adds menus to applications
  • Handle events generated when a user selects a menu item
  • Use keyboard mnemonics and accelerator keys

9.1.1: About Menus

  • A menu provides a space-saving way to let a user choose one of several options
  • Menus usually appears either in a menu bar or as a popup menu
  • Menu bar has one or more menus and is usually placed along the top of a window
  • Popup menus are typically displayed when a user right-clicks on a component
  • Menus have one or more menu items to select

Hierarchy of Classes for Menus

  • Following is a Swing hierarchy for working with menus
    • Has links to the class APIs
  • Since all inherit from JComponent, they work much like previous components
  • Similarly, menus and menu items inherit from AbstactButton
    • Work like other button classes
  javax.swing.JComponent
    |
    +--javax.swing.JMenuBar
    |
    +--javax.swing.JPopupMenu
    |
    +--javax.swing.JSeparator
    |
    +--javax.swing.AbstractButton
         |
         +--javax.swing.JMenuItem
              |
              +--javax.swing.JMenu
              |
              +--javax.swing.JCheckBoxMenuItem
              |
              +--javax.swing.JRadioButtonMenuItem

Classes for Menus

Class Description
JMenuBar Defines a menu bar
JPopupMenu Defines a menu that’s typically displayed when a user right-clicks on a component
JSeparator Defines a divider line between menu items
AbstractButton Defines common behavior for Swing button classes, including the JButton, JCheckBox, and JRadioButton classes
JMenuItem Defines an item on a menu
JMenu Defines a menu
JCheckBoxMenuItem Defines a menu item that works similarly to a check box
JRadioButtonMenuItem Defines a menu item that works similarly to a radio button

Useful Methods of AbstractButton

  • Methods isSelected and setSelected commonly used with JCheckBoxMenuItem and JRadioButtonMenuItem
  • isSelected returns true if the item is selected
  • setSelected(boolean) sets the button to either true or false

9.1.2: Adding Menus

  • Now add a menu bar that contains menus to an application
  • The menu bar is the bar below the title bar
  • A menu is one of the lists that drop down from a menu bar
  • To select a menu, the user clicks on the menu name

Code to Add Menus

  • Usually create menus in the constructor of the JFrame class
  • Menus added to the menu bar using the add(JMenu) method
  • Menu bar added to the JFrame using the setJMenuBar(JMenu) method
  • JMenu fileMenu = new JMenu("File");
    JMenu editMenu = new JMenu("Edit");
    
    JMenuBar menuBar = new JMenuBar();
    menuBar.add(fileMenu);
    menuBar.add(editMenu);
    
    setJMenuBar(menuBar);
    

Commonly-Used Constructors and Methods

Class Constructor/Method Description
JMenu JMenu(String) Creates a menu with the specified text.
JMenuBar JMenuBar() Creates a menu bar.
JMenuBar add(JMenu) Adds the menu item to a menu bar.
JFrame setJMenuBar(JMenu) Adds the menu bar to a JFrame.

For Example

import javax.swing.*;

public class MyMenu extends JFrame
{
    public MyMenu() {
        super("My Menu Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JMenu fileMenu = new JMenu("File");
        JMenu editMenu = new JMenu("Edit");

        JMenuBar menuBar = new JMenuBar();
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        setJMenuBar(menuBar);

        setSize(300, 100);
        setVisible(true);
    }

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


}

9.1.3: Adding Menu Items

  • Need to add menu items to a menu for most applications
  • Menu item: one of the items in a menu
  • Separator: a line that separates two menu items

Code to Add Menus

  • Menu items created with the JMenuItem(String) constructor
  • Also created with the JMenuItem(String, Icon) constructor
  • Menu items added to a menu using the add(JMenuItem) method
  • New code shown in bold
  • JMenuItem exitMenuItem = new JMenuItem("Exit");
    JMenuItem cutMenuItem = new JMenuItem("Cut");
    JMenuItem copyMenuItem = new JMenuItem("Copy");
    JMenuItem pasteMenuItem = new JMenuItem("Paste");
    JMenuItem selectAllMenuItem = new JMenuItem("Select All");
    ...
    JMenu fileMenu = new JMenu("File");
    JMenu editMenu = new JMenu("Edit");
    
    JMenuBar menuBar = new JMenuBar();
    menuBar.add(fileMenu);
    menuBar.add(editMenu);
    setJMenuBar(menuBar);
    
    fileMenu.add(exitMenuItem);
    editMenu.add(cutMenuItem);
    editMenu.add(copyMenuItem);
    editMenu.add(pasteMenuItem);
    editMenu.addSeparator();
    editMenu.add(selectAllMenuItem);
    
  • Note that you can add submenus just like we add menu items
  • For instance, we could add the edit menu to the file menu using:
  • fileMenu.add(editMenu);

Commonly-Used Constructors and Methods from JMenuItem

Constructor/Method Description
JMenuItem(String) Creates a menu item with the specified text.
JMenuItem(String, Icon) Creates a menu item with the specified text and icon.
addActionListener(ActionListener) Adds an ActionListener to the menu item.
getText() Returns a String of the text displayed in the menu item.
setEnabled(boolean) Enables or disables the menu item.

Commonly-Used Methods from JMenu

Constructor/Method Description
add(JMenuItem) Appends a menu item to the end of this menu.
addSeparator() Appends a new separator to the end of the menu.

For Example

import javax.swing.*;

public class MyMenu2 extends JFrame
{
    private JMenuItem exitMenuItem =
        new JMenuItem("Exit", 'x');
    private JMenuItem cutMenuItem = new JMenuItem("Cut");
    private JMenuItem copyMenuItem = new JMenuItem("Copy");
    private JMenuItem pasteMenuItem = new JMenuItem("Paste");
    private JMenuItem selectAllMenuItem =
        new JMenuItem("Select All");

    public MyMenu2() {
        super("My Menu Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JMenu fileMenu = new JMenu("File");
        JMenu editMenu = new JMenu("Edit");

        JMenuBar menuBar = new JMenuBar();
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        setJMenuBar(menuBar);

        fileMenu.add(exitMenuItem);
        editMenu.add(cutMenuItem);
        editMenu.add(copyMenuItem);
        editMenu.add(pasteMenuItem);
        editMenu.addSeparator();
        editMenu.add(selectAllMenuItem);

        setSize(300, 160);
        setVisible(true);
    }

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

9.1.4: Handling Menu Item Events

  • Menu items are descendants of AbstractButton and generate ActionEvents
  • Can handle ActionEvents just like we did for buttons
  • Can use a separate Action Handler class
  • ActionHandler actHandler = new ActionHandler();
    ...
    addMenuItem.addActionListener(actHandler);
    
  • We looked at several ways to implement handlers:
  • Can also use the current Frame as a listener
  • addMenuItem.addActionListener(this);
  • Second method is more convenient for interaction and synchronization
  • Can use getSource method to determine which menu item created the event

For Example

import java.awt.event.*;
import javax.swing.*;

public class MyMenu3 extends JFrame
        implements ActionListener
{
    private JMenuItem exitMenuItem =
        new JMenuItem("Exit", 'x');
    private JMenuItem cutMenuItem = new JMenuItem("Cut");
    private JMenuItem copyMenuItem = new JMenuItem("Copy");
    private JMenuItem pasteMenuItem = new JMenuItem("Paste");
    private JMenuItem selectAllMenuItem =
        new JMenuItem("Select All");

    public MyMenu3() {
        super("My Menu Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JMenu fileMenu = new JMenu("File");
        JMenu editMenu = new JMenu("Edit");

        JMenuBar menuBar = new JMenuBar();
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        setJMenuBar(menuBar);

        fileMenu.add(exitMenuItem);
        editMenu.add(cutMenuItem);
        editMenu.add(copyMenuItem);
        editMenu.add(pasteMenuItem);
        editMenu.addSeparator();
        editMenu.add(selectAllMenuItem);

        exitMenuItem.addActionListener(this);
        //Add listeners for other items...

        setSize(300, 160);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == exitMenuItem)
            System.exit(0);
        //Respond to events from other items...
    }

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

9.1.5: Using Keyboard Mnemonics

  • Keyboard mnemonics allow the user to use the keyboard to navigate menus
  • A mnemonic allows choosing an already visible menu item
  • To pull down a menu with an underlined letter, press Alt + letter key
  • After a menu item is selected, users can just press the key for the underlined letter

Code to Add Mnemonics

  • Can specify a mnemonic when constructing a menu item
  • JMenuItem exitMenuItem = new JMenuItem("Exit", 'x');
  • Can also use the setMnemonic method
  • fileMenu.setMnemonic('F');
    editMenu.setMnemonic('E');
    exitMenuItem.setMnemonic('x');
    

Commonly-Used Constructors and Methods

Class Constructor/Method Description
AbstractButton setMnemonic(int) Sets the keyboard mnemonic.
JMenuItem JMenuItem(String, int) Creates a menu item with the specified text and keyboard mnemonic.

For Example

import java.awt.event.*;
import javax.swing.*;

public class MyMenu4 extends JFrame
        implements ActionListener
{
    private JMenuItem exitMenuItem =
        new JMenuItem("Exit", 'x');
    private JMenuItem cutMenuItem = new JMenuItem("Cut");
    private JMenuItem copyMenuItem = new JMenuItem("Copy");
    private JMenuItem pasteMenuItem = new JMenuItem("Paste");
    private JMenuItem selectAllMenuItem =
        new JMenuItem("Select All");

    public MyMenu4() {
        super("My Menu Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JMenu fileMenu = new JMenu("File");
        JMenu editMenu = new JMenu("Edit");

        JMenuBar menuBar = new JMenuBar();
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        setJMenuBar(menuBar);

        fileMenu.add(exitMenuItem);
        editMenu.add(cutMenuItem);
        editMenu.add(copyMenuItem);
        editMenu.add(pasteMenuItem);
        editMenu.addSeparator();
        editMenu.add(selectAllMenuItem);

        exitMenuItem.addActionListener(this);
        //Add listeners for other items...

        fileMenu.setMnemonic('F');
        editMenu.setMnemonic('E');
        exitMenuItem.setMnemonic('x');

        setSize(300, 150);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == exitMenuItem)
            System.exit(0);
        //Respond to events from other items...
    }

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

9.1.6: Setting Accelerator Keys

  • Accelerator keys allow a user to select an item without pulling down a menu
  • Provides keyboard shortcuts to bypass navigating the menu hierarchy
  • Users can press the keystroke directly
  • Must be certain keystrokes do not conflict with existing key combinations

Code to Add Accelerators

  • Can create a keystroke using a static method of KeyStroke
  • KeyStroke key = Keystroke.getKeyStroke(
        KeyEvent.VK_X, ActionEvent.ALT_MASK));
    
  • Can specify an accelerator key using the setAccelerator method
  • exitMenuItem.setAccelerator(KeyStroke.getKeyStroke(
            KeyEvent.VK_X, ActionEvent.ALT_MASK));
    

Commonly-Used Constructors and Methods

Class Constructor/Method Description
AbstractButton setAccelerator(KeyStroke) Sets the key combination that invokes the action listeners.
KeyStroke getKeyStroke(int, int) Returns a KeyStroke corresponding to a key press.

For Example

import java.awt.event.*;
import javax.swing.*;

public class MyMenu5 extends JFrame
        implements ActionListener
{
    private JMenuItem exitMenuItem =
        new JMenuItem("Exit", 'x');
    private JMenuItem cutMenuItem = new JMenuItem("Cut");
    private JMenuItem copyMenuItem = new JMenuItem("Copy");
    private JMenuItem pasteMenuItem = new JMenuItem("Paste");
    private JMenuItem selectAllMenuItem =
        new JMenuItem("Select All");

    public MyMenu5() {
        super("My Menu Application");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JMenu fileMenu = new JMenu("File");
        JMenu editMenu = new JMenu("Edit");

        JMenuBar menuBar = new JMenuBar();
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        setJMenuBar(menuBar);

        fileMenu.add(exitMenuItem);
        editMenu.add(cutMenuItem);
        editMenu.add(copyMenuItem);
        editMenu.add(pasteMenuItem);
        editMenu.addSeparator();
        editMenu.add(selectAllMenuItem);

        exitMenuItem.addActionListener(this);
        //Add listeners for other items...

        fileMenu.setMnemonic('F');
        editMenu.setMnemonic('E');
        exitMenuItem.setMnemonic('x');

        exitMenuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_X, ActionEvent.ALT_MASK));

        setSize(300, 150);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == exitMenuItem)
            System.exit(0);
        //Respond to events from other items...
    }

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

Exercise 9.1

Take one minute to prepare answers to the following questions:

  1. How are menus added to an application?
  2. How are menu item events handled?
  3. How do accelerator keys and mnemonics differ?

9.2: Labels and Text Fields

Objectives

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

  • Use JLabels to display text and icons
  • Use text fields for displaying and entering data
  • Use JTextArea for displaying and entering data

9.2.1: Using Labels

  • JLabel displays text and images in a GUI
  • Labels are typically used to display text for other components

Code to Add Labels

  • Following code adds a label to a panel
  • JPanel panel = new JPanel();
    JLabel label = new JLabel("Label text");
    panel.add(label);
    
  • Other constructors of a JLabel allow Icons as well

Commonly-Used Constructors and Methods from JLabel

Constructor/Method Description
JLabel() Creates a blank label.
JLabel(Icon) Creates a label with the specified image.
JLabel(String) Creates a label with the specified text.
setIcon(Icon) Sets the icon for a label.
setText(String) Sets the text for a label.

For Example

import java.awt.*;
import javax.swing.*;

public class LabelDemo extends JPanel {
    private JLabel label1, label2, label3;

    public LabelDemo() {
        ImageIcon icon = new ImageIcon(
            "splat.gif",
            "A pretty but meaningless splat");
        setLayout(new GridLayout(3,1));

        label1 = new JLabel("Image and Text",
            icon, JLabel.CENTER);
        //Set position of text relative to the icon:
        label1.setVerticalTextPosition(JLabel.BOTTOM);
        label1.setHorizontalTextPosition(JLabel.RIGHT);
        label2 = new JLabel("Text-Only Label");
        label3 = new JLabel(icon);

        //Add labels to the JBufferedPane.
        add(label1);
        add(label2);
        add(label3);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("LabelDemo");
        frame.setDefaultCloseOperation(
            JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new LabelDemo());
        frame.pack();
        frame.setVisible(true);
    }
}

9.2.2: Using Text Fields

  • JTextField: single-line area in which user can enter text
  • JPasswordField: extends JTextField and hides characters that a user enters

Code for Text Fields

  • Code to declare a JTextField and a JPasswordField
  • JTextField login = new JTextField(10);;
    JPasswordField password = new JPasswordField("asecret");
    
  • Code to register the handlers
  • login.addActionListener(this);
    password.addActionListener(this);
    
  • Example code that works with text fields
  • String data = login.getText();
    String pass = password.getPassword();
    password.setText("asecret");
    login.setEditable(false);
    

Commonly-Used Constructors and Methods from JTextField

Constructor/Method Description
JTextField(int) Creates an empty text field with the specified number of columns.
JTextField(String, int) Creates a text field that starts with the text and contains the number of columns.
getText() Returns the text contained in the text field as a String object.
setText() Sets the text field to the specified String.
setColumns(int) Sets the number of columns for the text field.
setEditable(boolean) Sets whether this text field is editable or not.

For Example

  • Example 13.7 from textbook demonstrates use of JTextField and JPasswordField in a Swing GUI
  • import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class LoginPane extends JFrame
            implements ActionListener {
    
        private JTextField login;
        private JPasswordField password;
        private JButton loginButton;
    
        public static void main(String[] args) {
            new LoginPane();
        }
    
        public LoginPane() {
            super("Login Pane");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
    
            // Set the layout manager
            Container c = getContentPane();
            c.setLayout(new BorderLayout());
    
            // Create the fields and button
            login = new JTextField(10);
            password = new JPasswordField("asecret");
            loginButton = new JButton("Login");
    
            // Add components to the container
            c.add(login, BorderLayout.NORTH);
            c.add(password, BorderLayout.CENTER);
            c.add(loginButton, BorderLayout.SOUTH);
    
            // Add event handlers
            login.addActionListener(this);
            password.addActionListener(this);
            loginButton.addActionListener(this);
    
            pack();
            setVisible(true);
        }
    
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == login) {
                password.requestFocus();
            } else if ((e.getSource() == password)
                    || (e.getSource() == loginButton)) {
                JOptionPane.showMessageDialog(null,
                    "Login: " + login.getText()
                    + "\nPassword: "
                    + new String(password.getPassword()),
                    "Login Message",
                    JOptionPane.INFORMATION_MESSAGE);
            }
        }
    }
    

    Notes On Code

    login = new JTextField(10);
    
  • First JTextField contains an empty string
  • password = new JPasswordField("asecret");
    
  • JPasswordField contains text "Hidden text", but text appears as series of asterisks (*)
  • login.addActionListener(this);
    password.addActionListener(this);
    loginButton.addActionListener(this);
    
  • Register GUI components for ActionEvents
  • public void actionPerformed(ActionEvent e)
    
  • Method actionPerformed invoked when user presses Enter in GUI field
  • if (e.getSource() == login) {
        password.requestFocus();
    
  • Pressing return in first section requests focus for the next field

9.2.3: Using Text Areas

  • When multiple lines of text are needed, use JTextField
  • Works with the DocumentListener interface

Code for Text Areas

  • Use the constructors to specify the number of rows and columns
  • private JTextArea theText;
    theText = new JTextArea(LINES, CHAR_PER_LINE);
    
  • If the text area will receive more text than can be viewed, add the text area to a scroll pane
  • theText = new JTextArea(LINES, CHAR_PER_LINE);
    JScrollPane scroller = new JScrollPane(theText);
    
  • Use the setLineWrap and setWrapStyleWord methods to wrap lines in the text area
  • theText.setLineWrap(true);
    theText.setWrapStyleWord(true);
    
  • To get the code stored in the text area:
  • theText.getText();
  • To set the text of the text area:
  • theText.setText("some value");
  • To append more text to existing text:
  • theText.append("some more text");

For Example

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class MemoSaver extends JFrame
        implements ActionListener
{
    public static final int WIDTH = 600;
    public static final int HEIGHT = 300;
    public static final int LINES = 10;
    public static final int CHAR_PER_LINE = 40;

    private JTextArea theText;
    private String memo1 = "No Memo 1.";
    private String memo2 = "No Memo 2.";

    public MemoSaver() {
        setSize(WIDTH, HEIGHT);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setTitle("Memo Saver");
        Container contentPane = getContentPane();
        contentPane.setLayout(new BorderLayout());

        JPanel buttonPanel = new JPanel();
        buttonPanel.setBackground(Color.white);
        buttonPanel.setLayout(new FlowLayout());
        JButton memo1Button = new JButton("Save Memo 1");
        memo1Button.addActionListener(this);
        buttonPanel.add(memo1Button);
        JButton memo2Button = new JButton("Save Memo 2");
        memo2Button.addActionListener(this);
        buttonPanel.add(memo2Button);
        JButton clearButton = new JButton("Clear");
        clearButton.addActionListener(this);
        buttonPanel.add(clearButton);
        JButton get1Button = new JButton("Get Memo 1");
        get1Button.addActionListener(this);
        buttonPanel.add(get1Button);
        JButton get2Button = new JButton("Get Memo 2");
        get2Button.addActionListener(this);
        buttonPanel.add(get2Button);
        contentPane.add(buttonPanel, BorderLayout.SOUTH);

        JPanel textPanel = new JPanel();
        textPanel.setBackground(Color.blue);

        theText = new JTextArea(LINES, CHAR_PER_LINE);
        theText.setBackground(Color.white);
        theText.setLineWrap(true);
        theText.setWrapStyleWord(true);
        JScrollPane scroller = new JScrollPane(theText);
        textPanel.add(scroller);
        contentPane.add(textPanel, BorderLayout.CENTER);
    }

    public void actionPerformed(ActionEvent e) {
        String actionCommand = e.getActionCommand();
        if (actionCommand.equals("Save Memo 1"))
            memo1 = theText.getText();
        else if (actionCommand.equals("Save Memo 2"))
            memo2 = theText.getText();
        else if (actionCommand.equals("Clear"))
            theText.setText("");
        else if (actionCommand.equals("Get Memo 1"))
            theText.setText(memo1);
        else if (actionCommand.equals("Get Memo 2"))
            theText.setText(memo2);
        else
            theText.setText("Error in memo interface");
     }

    public static void main(String[] args)
    {
        MemoSaver guiMemo = new MemoSaver();
        guiMemo.setVisible(true);
    }
}

Further Information

Exercise 9.2

Take one minute to prepare answers to the following questions:

  1. How is the text set for a label?
  2. How can the text be retrieved from a text field?
  3. How can text in a text field be changed?

9.3: Dialogs

Objectives

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

  • Collect user input in an input dialog box
  • Show messages using a message dialog

9.3.1: About Dialogs

  • Java provides convenience classes for interacting with users
  • JOptionPane provides several static methods for constructing dialogs
  • Code for simple dialogs can be minimal
  • For instance, to show a simple input dialog:
  • JOptionPane.showInputDialog("First number:");
  • Produces the following input dialog
  • Most uses of dialogs are "one-liners" like the above

Commonly-Used Methods of JOptionPane

Static Method Description
showConfirmDialog Asks a confirming question, like yes/no/cancel.
showInputDialog Prompts for user text input.
showMessageDialog Tell the user about something that has happened.

Dialogs and Frames

  • Every dialog is dependent on a frame
  • When that frame is destroyed, so are its dependent dialogs
  • When the frame is iconified, its dependent dialogs disappear from the screen
  • Dialogs that JOptionPane provides are all modal
  • When a modal dialog is visible, it blocks user input to all other windows

9.3.2: Using Dialogs

  • Can easily collect single-line of text from a user
  • Use the JOptionPane.showInputDialog() method
  • This method provides an input dialog similar to the following:
  • Syntax for the simplest form of the method is:
  • showInputDialog(string)
    
  • Argument string is a prompt displayed within the input dialog box
  • For example, the following statement produces the input dialog shown
  • String s = JOptionPane.showInputDialog("First number:");
    
  • After the dialog is displayed, the program scans keyboard for input
  • As the user enters data, the dialog box displays the characters
  • Method showInputDialog returns a String data type containing user input
  • Need to save this data in a variable for processing

For Example

  • Let us create a SumOf2 program to use input dialogs
  • We will need three dialog boxes:
    1. Enter first number
    2. Enter second number
    3. Display results
  • Complete program shown below:
  • import javax.swing.*;
    
    public class SumOf2Dialog
    {
      public static void main(String[] args) {
        double num1, num2;
        String data, output;
    
        data = JOptionPane.showInputDialog("First number:");
        num1 = Double.parseDouble(data);
    
        data = JOptionPane.showInputDialog("Second number:");
        num2 = Double.parseDouble(data);
    
        output = "" + num1 + " + " + num2 + " = "
            + (num1 + num2);
        JOptionPane.showMessageDialog(null, output);
        System.exit(0);
      }
    }

  • We create the first dialog and get the user input:
  • data = JOptionPane.showInputDialog("First number:");
    num1 = Double.parseDouble(data);
    
  • Note that we parse the string to a double just like the previous program
  • Creating the second dialog and user input is similar
  • data = JOptionPane.showInputDialog("Second number:");
    num2 = Double.parseDouble(data);
    
  • To calculate and display the results:
  • output = "" + num1 + " + " + num2 + " = "
        + (num1 + num2);
    JOptionPane.showMessageDialog(null, output);
    
  • Finally, since this is a GUI program, we must tell the program when to exit
  • System.exit(0);
    

9.3.3: Dialog Arguments

  • Most methods of JOptionPane are overloaded to accept arguments
  • Both showInputDialog and showMessageDialog accept the following arguments

Commonly-Used Arguments in JOptionPane Methods

Argument Description
parentComponent An object representing the frame of the dialog box and controls its placement on the screen. If null is used, the dialog is centered on the screen.
messageString A descriptive message displayed in the dialog box.
titleString A title typically placed in the title bar above the dialog box.
messageTypeInt Indicates the type of icon to display in the dialog box. Use one of the fields of JOptionPane to choose the icon.

Icons provided by JOptionPane

Icon Message Type Description
ERROR_MESSAGE Displays an error icon.
INFORMATION_MESSAGE Displays an information icon.
WARNING_MESSAGE Displays an warning icon.
QUESTION_MESSAGE Displays an question icon.
  PLAIN_MESSAGE Does not display an icon.

Further Information

Exercise 9.3

Take one minute to prepare answers to the following questions:

  1. What package(s) must be imported to create dialogs?
  2. How many statements are usually needed to create a dialog?

9.4: Errors and Error Handling

Objectives

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

  • Describe the difference between checked and unchecked exceptions
  • Use the throws clause
  • Write code to handle exceptions
  • Use predefine exception classes
  • Write a class that defines a new exception

9.4.1: Errors and Exceptions

  • Java handles errors quite different than older high-level languages
  • Traditional approach is to require each method to return error codes
    • Must return specific values to indicate failures
  • Many possible problems with this approach:
    1. Requires the programmer to check for the error code to find if an error occurred
    2. Error handling becomes intermixed with normal processing code
      • Becomes more difficult to understand how the codes is supposed to work
    3. Error conditions must be the same type as the normal code return type
      • Error code must be a special value
  • All these problems can be solved
  • More elegant approach is to use exception handling

Terminology

  • Exception: an error condition that changes the normal flow of a program
  • Throw an exception: either the Java runtime or your code signals that something unusual happened
  • Catch an exception: take appropriate action to deal with an exception
  • Exception handler: the code that processes an exception

Exception Handling Program Flow

  • When an error occurs while a method is executing:
    1. Method stops processing at the failures point
    2. Creates and object with the error information
    3. Passes the exception object to the JVM
    4. JVM tries to locate the exception handling code
    5. If code cannot be found, the general exception handler is used
  • General exception handler produces an error messages on the console
Exception in thread "main" java.lang.NumberFormatException: null
        at java.lang.Integer.parseInt(Integer.java:394)
        at java.lang.Integer.parseInt(Integer.java:476)
        at DivideDialog.main(DivideDialog.java:10)
  • Note that the purpose of exception handling is not to reduce debugging time
  • Purpose of exception handling is to simplify the code for normal circumstances
  • However, general exception handler does provide information about where an error occurred

An Erroneous Program

  • Following is an erroneous program
  • Can you see the errors?

import javax.swing.*;

public class DivideDialog
{
  public static void main(String[] args) {
    int num1, num2;
    String data, output;

    data = JOptionPane.showInputDialog("Numerator:");
    num1 = Integer.parseInt(data);

    data = JOptionPane.showInputDialog("Denominator:");
    num2 = Integer.parseInt(data);

    output = "" + num1 + " / " + num2 + " = ";
    output += divide(num1, num2);
    JOptionPane.showMessageDialog(null, output);
    System.exit(0);
  }

  static int divide(int numerator, int denominator)
  {
    return numerator / denominator;
  }
}

  • What happens if the user enters a letter instead of a number?
  • What happens if the user presses the Cancel button?
  • What happens if the user enters 0 for the denominator?

9.4.2: Types of Exceptions

  • Two fundamental types of errors that cause exceptions

Checked Exceptions

  • First type happens because the program cannot get a resource
    • Problem is caused by the external resource
    • Programmer has no control over the resource
  • Java forces these types of problems to be provided for if they occur
  • Compiler checks that some mechanism is in place for receiving and processing the exception object
  • Since it is checked by the compiler, known as a checked exception
  • An example of this type of exception is the IOException
  • Programmer cannot prevent an I/O device failure (e.g. disk drive failure)
  • Thus, need to check if the condition has occurred

Unchecked Exception

  • Second type happens as a result of a programming error
  • Exceptions of this type can occur in the DivideDialog program
  • User can enter a string that cannot be converted to a number
  • Another example is when the user presses the Cancel button
  • Both of these errors can always be prevented by programming
    • If they occur in your homework programs, it will affect your score

9.4.3: Predefined Exception Classes

  • Many Java library classes throw exceptions
  • API documentation or class interface will tell you
  • Exceptions thrown are often also predefined
  • Some of them are shown in the following tree
java.lang.Throwable
  |
  +--java.lang.Error (Unchecked)
  |
  +--java.lang.Exception
       |
       +--java.lang.InterruptedException
       |
       +--java.io.IOException
       |
       +--java.lang.RuntimeException (Unchecked)
            |
            +--java.lang.ArithmeticException
            |
            +--java.lang.IllegalArgumentException
            |
            +--java.lang.IndexOutOfBoundsException
            |
            +--java.lang.NullPointerException
            |
            +--java.lang.NumberFormatException
  • Throwable is the root class of all exceptions
    • Has method getMessage to retrieve message generated by the exception
    • Another useful method is printStackTrace, which prints the method call stack
  • Error means that a serious problem has occurred
    • Applications should not try to catch these types of problems
  • Exception is the root class of exceptions that a reasonable program might catch
  • RuntimeException are errors caught by the JVM
    • Usually due to program bugs
  • All exceptions other than Error and RuntimeException (and subclasses) are checked exceptions
    • Compiler forces you to deal with the exception
  • Predefined exceptions usually include a meaningful message that is retrieved with method getMessage
  • System.out.println(e.getMessage());

9.4.4: Throwing an Exception

  • Any method that can cause an exception must deal with it
  • Easiest way to deal with an exception is to throw the exception to the caller
  • Throwing an exception is like passing the buck
    • Requires the calling method to deal with the exception
  • The calling method can also throw the exception
  • Eventually some method should catch it
    • Otherwise the general exception handler is used
  • General syntax for throwing an exception:
  • returnType functionName( paramterList )
            throws ExceptionType1, ExceptionType2,...
    {
        // method body
    }
    

How Exceptions are Propagated

  • Methods can call other methods that can throw an exception
  • This chain continues usually until one method catches the exception
  • Can also throw an exception from the main method
  • public static void main(String[] args)
      throws java.io.IOException
    
  • Throwing from main invokes the general exception handler
  • Produces an ugly (but useful to programmers) error message
Exception in thread "main" java.lang.NumberFormatException: null
        at java.lang.Integer.parseInt(Integer.java:394)
        at java.lang.Integer.parseInt(Integer.java:476)
        at DivideDialog.main(DivideDialog.java:10)

For Example

  • Can use throws clause in our DivideDialog program

import javax.swing.*;

public class DivideDialog1
{
  public static void main(String[] args)
      throws ArithmeticException
  {
    int num1, num2;
    String data, output;

    data = JOptionPane.showInputDialog("Numerator:");
    num1 = Integer.parseInt(data);

    data = JOptionPane.showInputDialog("Denominator:");
    num2 = Integer.parseInt(data);

    output = "" + num1 + " / " + num2 + " = ";
    output += divide(num1, num2);
    JOptionPane.showMessageDialog(null, output);
    System.exit(0);
  }

  static int divide(int numerator, int denominator)
      throws ArithmeticException
  {
    return numerator / denominator;
  }
}

9.4.5: Handling Exceptions

Syntax:

    try {
      // One or more statements at least one of which
      //   should be capable of throwing an exception
    } catch(MostSpecificException e) {
      // Exception handling code
    } catch(LeastSpecificException e) {
      // Exception handling code
    } finally {
      // Optional section that always executes
    }
    //Executes unless an uncaught exception is thrown

Try Block

  • Keyword try identifies the start of an exception handling block
  • At least one statement that could generate exceptions placed in try blocks

Catch Block

  • A try block must be followed by one or more catch blocks
  • Executes only if an exception is thrown

Finally Block

  • Optional section follows the catch blocks
  • Executes whether or not an exception is thrown
  • Usually used to dispose of external resources such as:
    • Database connections
    • File descriptors
    • Graphics contexts
    • Sockets
  • Most of these types of resources have a close or a dispose method
  • g.dispose();
  • Returns a scarce resource back to the operating system

Code After try-catch-finally

  • Executes unless an uncaught exception is thrown

For Example

  • Add exception handling to our DivideDialog program
  • Notice how the "normal" code is separated from the error handling code

import javax.swing.*;

public class DivideDialog2
{
  public static void main(String[] args)
  {
    int num1, num2;
    String data = null, output;

    try {
      data = JOptionPane.showInputDialog("Numerator:");
      num1 = Integer.parseInt(data);

      data = JOptionPane.showInputDialog("Denominator:");
      num2 = Integer.parseInt(data);

      output = "" + num1 + " / " + num2 + " = ";
      output += divide(num1, num2);
      JOptionPane.showMessageDialog(null, output);
    } catch(NumberFormatException e) {
      if (data == null) {
        JOptionPane.showMessageDialog(null,
            "You pressed the Cancel button",
            "Program Termination",
            JOptionPane.INFORMATION_MESSAGE);
      } else {
        JOptionPane.showMessageDialog(null,
            "You must enter a number",
            "Input Data Error",
            JOptionPane.ERROR_MESSAGE);
        main(args); // allows user to try again
        return;
      }
    } catch(ArithmeticException e) {
      JOptionPane.showMessageDialog(null,
          "You cannot enter 0 for the denominator",
          "Input Data Error",
          JOptionPane.ERROR_MESSAGE);
      main(args); // allows user to try again
      return;
    }
    System.exit(0);
  }

  static int divide(int numerator, int denominator)
      throws ArithmeticException
  {
    return numerator / denominator;
  }
}

9.4.6: Throwing Your Own Exceptions

  • Can trigger an exception by instantiating a new exception object
  • To throw a checked exception:
  • throw new Exception("Just checking");
  • To throw an unchecked exception:
  • throw new RuntimeException("Just testing");
  • Can also catch and rethrow an exception:
  • catch (IOException e) {
      System.err.println("IOException thrown in method");
      throw e;
    }
    
  • Note that all exception classes have two constructors
  • Overloaded constructor accepts a String message
  • Use the message string to explain the error

When to Throw an Exception

  • When a method encounters a situation where it cannot complete its task
    • For example: cannot write to an already-opened file
  • To report an error before handling the condition
    • For example: report an error to the user then ask to reinput data

9.4.7: Defining Your Own Exception Classes

  • Can define your own exception class
  • Must be derived from some already defined exception class
  • Often the only method you need to define is the constructor
  • Include a constructor that takes a String message argument
  • Also include a default constructor with a call to super and default message string
  • For example:
  • public class DivideByZeroException
            extends ArithmeticException
    {
        // default constructor with default error message
        public DivideByZeroException() {
            super("Attempted to divide by zero");
        }
    
        // constructor to allow customized error message
        public DivideByZeroException(String message) {
            super(message);
        }
    }
    
  • Using the new exception we have define:
import javax.swing.*;

public class DivideDialog3
{
  public static void main(String[] args)
  {
    int num1, num2;
    String data = null, output;

    try {
      data = JOptionPane.showInputDialog("Numerator:");
      num1 = Integer.parseInt(data);

      data = JOptionPane.showInputDialog("Denominator:");
      num2 = Integer.parseInt(data);

      output = "" + num1 + " / " + num2 + " = ";
      output += divide(num1, num2);
      JOptionPane.showMessageDialog(null, output);
    } catch(NumberFormatException e) {
      if (data == null) {
        JOptionPane.showMessageDialog(null,
            "You pressed the Cancel button",
            "Program Termination",
            JOptionPane.INFORMATION_MESSAGE);
      } else {
        JOptionPane.showMessageDialog(null,
            "You must enter a number",
            "Input Data Error",
            JOptionPane.ERROR_MESSAGE);
        main(args); // allows user to try again
        return;
      }
    } catch(DivideByZeroException e) {
      JOptionPane.showMessageDialog(null,
          e.getMessage(),
          "Input Data Error",
          JOptionPane.ERROR_MESSAGE);
      main(args); // allows user to try again
      return;
    } catch(ArithmeticException e) {
      JOptionPane.showMessageDialog(null,
          e.getMessage(),
          "Unknown Error",
          JOptionPane.ERROR_MESSAGE);
    }
    System.exit(0);
  }

  static int divide(int numerator, int denominator)
      throws ArithmeticException, DivideByZeroException
  {
    if (denominator == 0)
      throw new DivideByZeroException(
        "You cannot enter 0 for the denominator");
    return numerator / denominator;
  }
}

When to Define Your Own Exceptions

  • When you use a throw-statement in your code you usually define your own exception class
  • Using a predefined, more general exception class means your catch-block will have to be general
  • General catch-block could also catch exceptions that should be handled somewhere else
  • Specific catch-block for your own exception class will catch the exceptions it should and pass others on

Exercise 9.4

Take one minute to prepare answers to the following questions:

  1. What output is produced by the following code?
  2. class WaitTimeException extends Exception {
        public WaitTimeException() {
            super("Time expired");
        }
    
        public WaitTimeException(String message) {
            super(message);
        }
    }
    
    public class WaitTime {
        public static void main(String[] args) {
            int waitTime = 50;
            System.out.println("Before try-block");
            try {
                System.out.println("Entering try-block");
                if (waitTime > 30)
                    throw new WaitTimeException();
                System.out.println("Exiting try-block");
            } catch(WaitTimeException e) {
                System.err.println("Exception: "
                    + e.getMessage());
            } catch(Exception e) {
                System.err.println("Exception: "
                    + e.getMessage());
            } finally {
                System.out.println("Finally done");
            }
            System.out.println("After catch-block");
        }
    }
    

Wrap Up

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

Last Updated: November 08 2003 @16:38:21