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.
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.
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.
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 © 2024 Ian Finlayson | Licensed under a Creative Commons BY-NC-SA 4.0 License.