Home CPSC 330

GUI Programming

Overview

Graphical User Interfaces provide users with a familiar way of interacting with a program.

Xerox's PARC is widely credited with creating the first GUI-based computer systems. Xerox also developed SmallTalk, one of the firsy object-oriented programming languages.

Object-oriented programming and GUIs have developed together.


Executing GUI Applications

Unfortunately, executing GUI applications over SSH is troublesome.

There are three options for developing GUI programs:

  1. Run them in the lab.
  2. Install the Java development on your own computer and run them locally.
  3. Install an X server, setup X forwarding and run them over SSH.

Swing Hello World

The GUI library that comes with Java is called Swing. Below is a hello world program in Swing:


import javax.swing.*;

public class HelloWorld {
  public static void main(String args[]) {
    // create and set up the window.
    JFrame frame = new JFrame("Hello World!");

    // make the program close when the window closes
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // add a "Hello World" label.
    JLabel label = new JLabel("Hello World");
    frame.getContentPane().add(label);

    // display the window.
    frame.pack();
    frame.setVisible(true);
  }    
}

The JFrame class represents a window.

The JLabel class represents a textual label.


Buttons

The following example demonstrates a button added to the window instead of a label:


import javax.swing.*;

public class Buttons {
  public static void main(String args[]) {
    // create and set up the window.
    JFrame frame = new JFrame("Button Example!");

    // make the program close when the window closes
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // add a button object
    JButton button = new JButton("Push Me!");
    frame.getContentPane().add(button);

    // display the window.
    frame.pack();
    frame.setVisible(true);
  }    
}

Unfortunately clicking the button does nothing.


Events

GUI programs work much differently from console programs. In a GUI program, the control of execution is not linear. Instead, the program responds to the users actions via events.

To make our button take some action when it is pressed, we need to use events.

This example shows adding an event handler for the button:


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

class ButtonListener implements ActionListener {
  public void actionPerformed(ActionEvent e) {
    JOptionPane.showMessageDialog(null, "You pushed the button!!");
  }
}

public class Buttons2 {
  public static void main(String args[]) {
    // create and set up the window.
    JFrame frame = new JFrame("Button Example!");

    // make the program close when the window closes
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // add a button object
    JButton button = new JButton("Push Me!");
    button.addActionListener(new ButtonListener());
    frame.getContentPane().add(button);

    // display the window.
    frame.pack();
    frame.setVisible(true);
  }    
}

Here, the actionPerformed method is called automatically when the button is pressed.

This also demonstrates creating a message box.


This example shows shows using a menu bar:


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

public class Menu {

  public static void main(String[] args) {
    JFrame frame = new JFrame("Menu Example!");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // create the menu bar
    JMenuBar menubar = new JMenuBar();

    // add the file menu
    JMenu file = new JMenu("File");
    file.setMnemonic(KeyEvent.VK_F);

    // add a menu item
    JMenuItem exit = new JMenuItem("Exit", null);
    exit.setMnemonic(KeyEvent.VK_E);
    exit.setToolTipText("Exit the program");
    
    // add the action as a new anonymous object
    exit.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.exit(0);
      }   
    }); 
    file.add(exit);

    // add file to the menubar
    menubar.add(file);

    // add the menubar to the window
    frame.setJMenuBar(menubar);

    // set other things
    frame.setTitle("Simple menu");
    frame.setSize(300, 200);
    
    // launch the windwo
    frame.setVisible(true);
  }
}

This example also shows a Java feature called an anonymous inner class When we call exit.addActionListener(), we create an object insider of the parameter list. We also override the actionPerformed method for the object.

This is often used as it is more convenient than including the class somewhere else in the program.


Layouts

Typically GUI programs will use more than one GUI component at a time. When doing this, we'll need to specify how they appear together. This is done with layouts in Swing.

The simplest layout is the BoxLayout which specifies that elements in it appear in a vertical or horizotal list.

The following example demonstrates the box layout.


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


class ButtonListener implements ActionListener {
  public void actionPerformed(ActionEvent e) {
    JOptionPane.showMessageDialog(null, "You pushed the button!!");
  }
}

public class ManyButtons {
  public static void addButton(final String text, JFrame f) {
    // add a button object
    JButton button = new JButton(text);
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        JOptionPane.showMessageDialog(null, "You pushed button " + text);
      }   
    }); 
    f.getContentPane().add(button);
  }

  public static void main(String args[]) {
    // create and set up the window.
    JFrame frame = new JFrame("Button Example!");

    // make the program close when the window closes
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // create the box layout
    frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));

    // add some buttons
    addButton("A", frame);
    addButton("B", frame);
    addButton("C", frame);
    addButton("D", frame);

    // display the window.
    frame.pack();
    frame.setVisible(true);
  }    
}

Layouts can also be nested. For example, you can have a BoxLayout inside of a BorderLayout.


Swing Class Hierarchy

The Swing library is quite large and complex. The class hierarchy is listed here.

One important class is the JComponent class which is the base class for most of the GUI element classes.

This allows for all of the elements to be treated in the same way - such as to add them to a window, or connect actions.

As there are so many classes in the Swing library, writing GUI programs requires reading the documentation.


Icons

Swing can use image icons in several places, frames, menus, buttons, labels and so on. Using icons in GUI programs can make them easier to use.

The following example demonstrates a few uses of icons:


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

public class Icons {

  public static void main(String[] args) {
    JFrame frame = new JFrame("Menu Example!");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // load an icon
    Image icon;
    try {
      icon = ImageIO.read(new File("star.png"));
    } catch(Exception e) {
      icon = null;
    }

    // set it as window icon
    frame.setIconImage(icon);
    
    // create the menu bar
    JMenuBar menubar = new JMenuBar();

    // add the file menu
    JMenu file = new JMenu("File");
    file.setMnemonic(KeyEvent.VK_F);

    // add a menu item with an icon
    JMenuItem exit = new JMenuItem("Exit", new ImageIcon(icon));
    exit.setMnemonic(KeyEvent.VK_E);
    exit.setToolTipText("Exit the program");
    
    // add the action as a new anonymous object
    exit.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.exit(0);
      }   
    }); 
    file.add(exit);

    // add file to the menubar
    menubar.add(file);

    // add the menubar to the window
    frame.setJMenuBar(menubar);

    // add a button object
    JButton button = new JButton(new ImageIcon(icon));
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        JOptionPane.showMessageDialog(null, "You pushed the button!!");
      }   
    }); 
    frame.getContentPane().add(button);


    // set other things
    frame.setTitle("Simple menu");
    frame.setSize(300, 200);
    
    // launch the windwo
    frame.setVisible(true);
  }
}

For this code to work, the star.png image file must be in the same directory as the program!


Dialogs

This example shows a more complex Dialog:


// Dialog.java

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

public class Dialog {
  // method to present a dialog question to the user
  private static int askQuestion(String question, Object[] options) {
    int n = JOptionPane.showOptionDialog(null, question,
        "Question!", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,
        null, options, options[0]);

    // return which option was chosen
    return n;
  }

  public static void main(String args[]) {
    // create and set up the window.
    JFrame frame = new JFrame("Dialogs!");

    // make the program close when the window closes
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // add a button that launches a dialog
    final JButton button = new JButton("Push Me!");
    button.addActionListener(new ActionListener() {
        // this method is called when the button is pressed
        public void actionPerformed(ActionEvent e) {
          final String[] options = {"Push Me!", "Panic!", "&%$Q#&%#**"};
          int which = askQuestion("What would you like the button to say?", options);

          String text;
          if(which == -1) {
            text = "You closed the dialog!!!!";
          } else {
            text = options[which];
          }

          button.setText(text);
        }   
        }); 
    frame.getContentPane().add(button);

    // display the window.
    frame.setSize(300, 400);
    frame.setVisible(true); 


  }
}

Notice that the JOptionPane.showOptionDialog returns an int that indicates which option (if any) the user selected.

We also use the setText method of a button to change its message.

Copyright © 2018 Ian Finlayson | Licensed under a Creative Commons Attribution 4.0 International License.