The goal of this lab is to practice using Java's GUI capabilities to write programs that use windows and buttons.
We'll start by looking at some example programs, including the two that were in the handout.
Clone the repository from the class public directory and move into
the examples
subdirectory:
hg clone /cslab/class/csci235/lab15 cd lab15/examples
Start by looking at Example1.java
. This program
simply puts up a window (JFrame
that contains two instances of
JLabel
. There are two statements that configure the
window, setting its size and initial location on the screen; the unit
of measurement is the pixel, short for picture
element, which is the smallest dot the screen displays.
Throughout the GUI libraries, dimensions and coordinates are specifies
as row, column, with row zero at the top of the screen and
column zero at the left edge.
The other bit of configuration to notice is the call to
setDefaultCloseOperation()
. This tells the program to
exit when you close this window.
Compile and run this program:
javac Example1.java java Example1Notice that the program does not exit when it reaches the end of the
main()
method. Instead, the program stays around
waiting for events. To quit the program, close the window by clicking
on the "X" decoration at the upper left.
Modify Example1.java
, changing the size of the window
to be wider than it is tall, and to move its starting location lower
on the screen. Compile and run it with your changes.
Note that you can resize the window while the program is running, by "grabbing" an edge or corner with the mouse and dragging it. Notice how the grid layout tries to adapt as you change the shape and size of the window.
Modify the program again, replacing the GridLayout(2,
1)
with a FlowLayout()
. Compile and run the new
version, and compare how the layout adjusts to changes in the window
size and shape.
Now take a look at Example2.java
, which is almost the
same as the earlier program, but replaces the second
JLabel
with a JButton
. The button can
produce an event when it is clicked; so this version of the
program calls the button's addActionListener()
method to
specify the listener object that should be called when the event
fires.
Look at OkListener2.java
. Notice that this class
implements the ActionListener
interface, which requires
it to provide a method actionPerformed()
.
Compile and run Example2
. You can try resizing this
one as you did for the previous program. What do you expect to happen
when you click on the button? Give it a try.
Now modify Example2.java
by commenting out the first
call to addActionListener()
and uncommenting the second.
Before you compile and run the program, see if you can predict what
will happen. Give it a try. Peek here if you
need help figuring out how to get back.
Now it is time to try a more interesting program.
A Fifteen Puzzle (or, more generally, an N-puzzle) consists in a grid of square, same-sized tiles, with all but one of the grid positions filled. The object of the game is to rearrange the tiles by sliding the tiles one at a time until a certain configuration is reached (for example, starting from a random configuration until the numbers are in order).
In this lab, you will write a program that simulates a Fifteen Puzzle
Change into this lab's other subdirectory, with
cd ../puzzle
Open FifteenPuzzle.java
in xemacs and read through it.
Notice that it basically adds sixteen buttons to the window.
Compile and run, and notice that the buttons are put right on top of each other,
and all of the buttons contain a number in the range 0 to 15.
Based on what you've seen so far, play around with the size, location, and layout management until you can see that you have sixteen buttons arranged in a square.
Each button stands for a tile or block in the puzzle. 15 of them will have numbers, and the 16th will be blank. We won't actually move the buttons around; instead, we will change the numbers on the buttons to give the appearance of moving tiles.
When a button is clicked, the following should happen:
Each button needs to have an action listener to perform this.
Uncomment the relevant sections in FifteenPuzzle.java
.
We are using an action listener class called PuzzlePiece
.
The skeleton of this class is given to you. You'll need to supply the
methods to complete it, but be sure that you read the rest of this
section before you start trying to write code. The methods needed are:
PuzzlePiece(JButton, int)
.
This is the constructor, and it tells the action listener what button it is attached to
and the number in the order the buttons where made (1 to 15, with the
last one numbered 0).
In addition to initializing the instance variables,
this constructor should also set the button's text
(hint: you might as well start it out with the int the constructor receives,
except that the 16th button should be blank).
addNeighbor(PuzzlePiece)
.
When a button is clicked, it affects its neighbors.
The action listener is not going to have direct access to the
neighboring buttons,
but it should have references to the action listeners attached to
those buttons.
Think about: We will need to have access to these neighbors later
when writing actionPerformed()
.
How can we store this information for later reuse?
Hint: Notice that not all PuzzlePiece
s have
the same number of neighbors.
actionPerformed(ActionEvent)
.
This method should implement the algorithm described above.
Hint: Notice again that when a button is clicked, its action listener
must communicate with the action listeners on the neighboring buttons---first,
to determine if one of the neighbors is blank; second, to
make any necessary changes.
How can you do this?
You may want to write a few extra methods in the class PuzzlePiece
.
You will need to make a few changes to the main()
method in FifteenPuzzle.java
. First, you should
uncomment the two sections of code that are marked. You will also
need to change the JButton
constructor call (or add
something else) so that the last button (number 0) is initially blank.
Turn in your .java
source files from the puzzle
directory with the command
/cslab/class/csci235/bin/handin lab15 PuzzlePiece.java FifteenPuzzle.java
Be sure to include all of your files on a single command.
Hint: When the
Example2
window disappears, the program is still running,
but you no longer have a way to interact with it. You can kill it by
typing a
Click here to jump back to where you were in the lab.