[ Home || Sun Java Docs || AlarmClock || ShakeyMessage | Message || Tetris | Piece | Score | Board || Documentation ]
Swing is a collection of graphical user interface (GUI) components that runs uniformly on any native platform which supports the JVM. Because they are written entirely in Java, these components typically provide functionality above and beyond that provided by the older java.awt package. The abstract window toolkit (awt) relies on native-platform equivalents and so its functionality is limited to the lowest common denominator of all native platforms.
In this session we will be making use the following classes from the indicated packages. Consult the Sun documentation on these classes as needed.
We will perform three experiments, each of which should take about 20 minutes.
Download the six Java source files, which are linked on the navigation bar at the top of this page, to your CFS directory.
Download the starter version of this class to your folder and read the documentation. Try the following experiments. The desired output is shown in the transcript below. However two of the methods are not implemented properly, so you'll get different results. Try to figure out how to define the two incorrect methods properly. You may have to consult the Java documentation for the javax.swing.Timer class and the documentation for AlarmClock (the link is at the top of this page.)
> AlarmClock a = new AlarmClock("time for class!");
> a.isSet()
false
> a.getMessage()
"time for class!"
> a.goOff()
time for class!
> a.getDelay()
0
> a.setDelay(2000);
> a.getDelay()
2000
> a.set(); /* the alarm will go off in two seconds */
> a.isSet()
true
time for class!
> a.isSet()
false
> AlarmClock.SNOOZE_DELAY
5000
> a.snooze(); /* the alarm will go off in five seconds */
> a.getDelay()
5000
time for class!
> a.isSet()
false
> AlarmClock.REPEAT_DELAY
300
> a.setRepeats(true); /* causes the alarm to go off repeatedly
at 300ms intervals */
> a.setDelay(0);
> a.setMessage("beep");
> a.set(); /* the alarm will immediately since delay is zero */
beep
beep
beep
beep
beep
beep
beep
beep
beep
> a.snooze() /* alarm stops, then goes off again after 5 seconds */
beep
beep
beep
beep
beep
beep
> a.turnOff()
Experiment with the Message class to see how it works.
Run the main method in the ShakeyMessage class like this;
> java ShakeyMessage
Notice that the button is unresponsive.
A ShakeyMessage is a custom JComponent, that is placed on a JFrame by main. A JComponent is-a Container, which means we can add other GUI components to it. In the constructor, we create and add one component, a JButton. Since the layout manager of a JComponent is null, by default, we'll explicitly set the layout to an instance of FlowLayout, which means that the manager will take care of sizing and positioning the button appropriately.
There are two interesting aspects to this program: how to animate the message string and how to make the button reactive to a press.
There are two ways to create a thread class in Java. One is to extend the Thread class, in which case your class is-a Thread. If you examine the documentation for the Thread class, you'll discover the following essential points:
The first two points are related. The Runnable interface is defined as follows:
public interface Runnable {
public void run();
}
Thus, in order for Thread to satisfy its Runnable contract, it must provide a definition of run. Here's the how Thread defines run:
public void run() {
}
Just creating a Thread object, however, isn't enough to actually create a separate process in the system. The computation that the thread is to perform must be specified in its run method and the thread must be initiated by calling its start method. Note: You should never call run directly since this does not spawn a new process; consequently, the code in the run method is executed in the calling thread.
So, in a nutshell, here's one way to go about creating a Thread.
Unfortunately, this approach will not work for us because our custom component will already have a parent (the JComponent class) so we can't use inheritance to make the object a thread.
Instead, we specify that our class implements the Runnable interface and then define a run method. An instance of our class will not be a thread, but we can create a thread from ourselves because we are a Runnable. We use new Thread(this) to create a thread object and then initiate our run method by starting the thread we created.
We will now bring the concepts we've learned together in one program to play the game of Tetris.
Fortunately, the basic set-up is the same as in the previous program. We create a custom JComponent and place it on a JFrame.
You can run Tetris like this:
> java Tetris
Read the accompanying documentation and experiment with the individual classes in DrJava.