Home CPSC 240

More GUI & Graphics Programming

 

Dialog Windows

Dialogs are windows that pop open from a GUI program asking for information. In Swing they can be created with the JOptionPane class, which contains static methods for creating different types of dialog windows.

One is the showConfirmDialog method which will pop up a window with buttons the user can click and return the results back to us. This can be used to make a program which confirms if the user really wants to quit when they click the close button.

The first step is to make it so the window does nothing by default when we hit the close button:


frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Then we need to make a WindowListener which is like an ActionListener except that it listens for events that happen to a window. This interface has seven different methods we must override to implement the interface. However, for this example, we only care about one of them, the windowClosing method which will be called when the user clicks the close button. In this handler, we ask if the user really wants to close with a dialog:


    // this is called when the user tries to close the window
    public void windowClosing(WindowEvent e) {
        int choice = JOptionPane.showConfirmDialog(null, "Are you sure you want to quit?",
                "Really Quit?", JOptionPane.YES_NO_OPTION);

        if (choice == JOptionPane.YES_OPTION) {
            frame.dispose();
        }
    }

This code asks the user to confirm and, if so, closes the frame by calling the dispose method. To do this, it needs to have a reference to the window. This is done by storing it inside the WindowListener as an instance variable. Then we pass it in when making the object:


        frame.addWindowListener(new WindowHandler(frame));

The complete example can be seen in ReallyQuit.java.


 

Graphics

In addition to the built in graphical components that come with Swing, we can also create our own custom components. The reason to do this is to make graphical programs where we draw whatever we want onto the screen.

In order to do this, we can make our own subclass of the JComponent class. Then we override the paintComponent method to draw the component. This example demonstrates this:


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

// the gameworld is a component, so it can be added to a GUI program
class Canvas extends JComponent {
    @Override
    // overriding this method changes how it is shown
    public void paintComponent(Graphics g) {
        // just draw a black line on the window
        g.setColor(Color.green);
        g.fillOval(200, 200, 100, 100);
    }
}

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

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

        // add the GameWorld component
        frame.add(new Canvas());

        // display the window.
        frame.setSize(500, 500);
        frame.setVisible(true);
    }
}

Here our Canvas class is a subclass of JComponent, which allows it to be added to the window. Then the window will call the paintComponent method to get it drawn. We override the method to draw whatever we want to the window. This method takes a Graphics object as a parameter. We can use this to draw a variety of shapes and things to the component.

The coordinate system being used starts with the origin (0, 0) in the upper-left hand corner of the window. The X coordinate increases to the right and the Y coordinate increases down.


 

Snow Example

An example of a complete, but very simple, program using this technique is Snow.java. This program creates a snowy scene by overriding the paintComponent method to draw a number of snow flakes to the component. They begin randomly positioned and move around.

There are two ways to create movement in a computer program. The first is to move the objects a fixed amount every frame. This is simple to implement but results in programs that move faster on fast computers than they do on slower ones.

The other way is framerate independent movement wherein we take time into account. In this method, the objects will move the same distance on slow computers as on fast ones, but will move more smoothly on faster computers. To do this, we need to multiply all movements by the elapsed time since the last frame. This is done like this:


        // calculate the number of seconds since the last update
        long time_now = new Date().getTime();
        long elapsed_ms = time_now - last_time;
        double dt = elapsed_ms / 1000.0;

        // update each flake with this elapsed time
        for (Flake f : snow) {
            f.update(dt);
        }

        // save the current time as the last time
        last_time = time_now;

We get the amount of time in seconds since the last frame. We then pass it to the method the snow flakes use to update themselves. They then multiply this by their speed to get the amount they need to move.


 

Animation

As a final example, we have a program which creates an animation. The program is broken into three files and contains 4 images as well. The program is available in animation/.

This program keeps an array of images and cycles between them, drawing them to the screen in sequence to create the illusion of movement. It also demonstrates how to do keyboard input in a Swing program.

Copyright © 2022 Ian Finlayson | Licensed under a Attribution-NonCommercial 4.0 International License.