2 COMP10081 Graphical User Interfaces
Why?
With the dominance of windows-based systems, Graphical User Interfaces (GUIs) are everywhere.
They have a number of useful characteristics. – They can allow us to present large amounts of information in a concise
manner. – They can make it easier to allow the user to interact with the state of an
application and control its execution.
– They can look much nicer than command line programs.
3 COMP10081 Graphical User Interfaces
Example GUIs
GUIs are not always the answer to our problems though, and there are issues relating to their use that we need to be aware of:
– Human factors – Interface design
4 COMP10081 Graphical User Interfaces
Coming up...
Java has a wealth of support for building GUIs. GUIs rely on a number of features of the Java language that we have
not yet seen in depth. This includes extending existing classes; In our initial examples, we will also meet a number of new concepts
relating to GUIs: – Frames, Windows, Components, Containers.
The next few lectures will introduce these topics. By the end of these lectures you should know enough to be able to
build simple Graphical User Interfaces.
5 COMP10081 Graphical User Interfaces
Aside: Swing vs. AWT
The original versions of Java contained components for windowing known as the AWT (Abstract Window Toolkit).
Swing provides replacements for most of the AWT graphical components, but a number of non-component AWT classes (such as Container) are still in use.
It is recommended that you do not mix Swing and AWT components in a single application as this is likely to cause problems.
Swing is slightly more complicated, but is now more widely used. We will use Swing in our examples.
6 COMP10081 Graphical User Interfaces
Example: HelloWord
In the best traditions of programming, our first example will be a “Hello World” program.
This simply makes a window appear on the screen with a message.
HelloWorld
7 COMP10081 Graphical User Interfaces
HelloWorld
The example program does the following: – Create an object representing a new window which will be displayed on
the screen;
The constructor method adds a label to the window; – Display the window.
To understand this we need to understand how to add things to windows which appear on the screen.
This is done using Containers and Components.
8 COMP10081 Graphical User Interfaces
Components and Containers
The elements we use to build up GUIs are known as Components. – Components include Buttons, Labels, Text Fields and other things that
appear on GUIs.
– All components are kinds of java.awt.Component. – We often refer to the components that appear on GUIs as widgets.
Some Components are Containers – these are objects that contain other components.
Containers allow us to build up GUIs in sections or pieces which are then assembled together.
An example of a container is JPanel.
9 COMP10081 Graphical User Interfaces
Components
Buttons
List
Text Box
Labels
10 COMP10081 Graphical User Interfaces
Top Level Containers and JFrame
Swing provides a number of special kinds of container known as Top Level Containers, one of which is JFrame.
A JFrame is a window that typically has decorations such as a border, a title, and buttons for closing and iconifying the window. – Applications with a GUI will in general use at least one frame. – Otherwise it’s probably not a Graphical User Interface!!
11 COMP10081 Graphical User Interfaces
JFrame Anatomy
Frame content
Menu bar
Window controls added by host windowing system
Window Title
12 COMP10081 Graphical User Interfaces
JFrame
JFrame also allows us to add menu bars or toolbars to windows. – The position of menu bars may be left up to the host windowing systems.
For example, on the Macintosh, menu bars tend to appear at the top of the desktop rather than at the top of the window.
13 COMP10081 Graphical User Interfaces
A Simple Frame Example
Our first example creates a new Frame, gives it a title, then asks it to display.
import javax.swing.JFrame;
public class SimpleFrame {
/* Main method to drive the program */ public static void main(String [] args) {
JFrame theFrame = new JFrame(); theFrame.setTitle("A Frame"); theFrame.setSize( 300, 200 ); theFrame.setVisible( true );
} // main
} // SimpleFrame
SimpleFrame
14 COMP10081 Graphical User Interfaces
Extending Existing Classes
Class libraries such as JFrame provide code that we can reuse in our applications. – We don’t want to have rewrite our own classes for basic GUI
components. There are a number of different ways that we can use JFrame. For example, we could have an instance variable which is a JFrame,
and then delegate any operations relating to the window to this instance variable.
This would work, but in this case an alternative is to extend an existing class. – Instance of our new class are then also instances of JFrame.
Extending allows us to provide a specialisation of a class. We can reuse the code in the class and add additional instance
variables or methods that perform some particular task for our application.
15 COMP10081 Graphical User Interfaces
Extending Existing Classes
The class that is extended is known as the superclass or base class. The class that is doing the extending is known as the subclass or
derived class. The derived class can directly use public methods and instance
variables. In our example, the statement at the beginning of the class declaration
states that we are extending JFrame.
import java.awt.Container; import javax.swing.JLabel; import javax.swing.JFrame;
public class HelloWorld extends JFrame { ... } // HelloWorld
• We can now use methods from JFrame within our class.
16 COMP10081 Graphical User Interfaces
HelloWorld main()
The first thing we do is create a new instance of the HelloWorld class using the constructor.
/* Main method to drive the program */ public static void main(String [] args) {
HelloWorld theHelloWorld = new HelloWorld(); theHelloWorld.setVisible( true ); } // main
• Our class has a main() method that drives the program.
17 COMP10081 Graphical User Interfaces
HelloWorld constructor
The constructor allows us to create new instances of our HelloWorld class
Before any of the code in the method is executed, the no-argument constructor of the base class will be called. – This could take care of any initialisation that might be required for the
instance variables that come with JFrame.
/* Constructor */ public HelloWorld()
setTitle("Hello World"); /* Get the contents of the frame and add a label to it */ Container contents = getContentPane();
contents.add(new JLabel("Hello World!"));
/* Specify appropriate behaviour when the window is closed */ setDefaultCloseOperation(EXIT_ON_CLOSE);
/* pack the frame */ pack(); } // HelloWorld
18 COMP10081 Graphical User Interfaces
HelloWorld constructor
A method from the base class is used to set the title of the window. – This is the title that the host windowing system will place on the title bar
of the window.
– This is also usually also the name that is shown when the window is reduced to an icon.
/* Constructor */ public HelloWorld()
setTitle("Hello World"); /* Get the contents of the frame and add a label to it */ Container contents = getContentPane();
contents.add(new JLabel("Hello World!"));
/* Specify appropriate behaviour when the window is closed */ setDefaultCloseOperation(EXIT_ON_CLOSE);
/* pack the frame */ pack(); } // HelloWorld
19 COMP10081 Graphical User Interfaces
HelloWorld constructor
By default, a JFrame is empty, and contains no components. – The JFrame has an area known as the content pane, which contains the
contents of the window. – When we add components to a JFrame, we don’t add them to the
JFrame itself, but instead add them to the content pane. We get the contentPane of the JFrame, which is a Container
– Note the use of a method from the base class.
/* Constructor */ public HelloWorld()
setTitle("Hello World"); /* Get the contents of the frame and add a label to it */ Container contents = getContentPane();
contents.add(new JLabel("Hello World!"));
/* Specify appropriate behaviour when the window is closed */ setDefaultCloseOperation(EXIT_ON_CLOSE);
/* pack the frame */ pack(); } // HelloWorld
20 COMP10081 Graphical User Interfaces
HelloWorld constructor
We then add a label to the content pane, using a new instance of JLabel – JLabel provides areas on a GUI for short pieces of text or images – The user cannot interact with labels.
/* Constructor */ public HelloWorld()
setTitle("Hello World"); /* Get the contents of the frame and add a label to it */ Container contents = getContentPane();
contents.add(new JLabel("Hello World!"));
/* Specify appropriate behaviour when the window is closed */ setDefaultCloseOperation(EXIT_ON_CLOSE);
/* pack the frame */ pack(); } // HelloWorld
21 COMP10081 Graphical User Interfaces
HelloWorld constructor
The above lines tell the window how it should behave when the user closes it. – In this case, we want the application to exit. – Another option would be to simply close the window, but keep the
object representing the window – we might want to show it again later.
/* Constructor */ public HelloWorld()
setTitle("Hello World"); /* Get the contents of the frame and add a label to it */ Container contents = getContentPane();
contents.add(new JLabel("Hello World!"));
/* Specify appropriate behaviour when the window is closed */ setDefaultCloseOperation(EXIT_ON_CLOSE);
/* pack the frame */ pack(); } // HelloWorld
22 COMP10081 Graphical User Interfaces
HelloWorld constructor
Finally, we call the pack() operation. This causes the window to be resized to fit the various constraints of its components. – In this case, it means that the window will be resized to fit the
dimensions of the label that we have added.
/* Constructor */ public HelloWorld()
setTitle("Hello World"); /* Get the contents of the frame and add a label to it */ Container contents = getContentPane();
contents.add(new JLabel("Hello World!"));
/* Specify appropriate behaviour when the window is closed */ setDefaultCloseOperation(EXIT_ON_CLOSE);
/* pack the frame */ pack(); } // HelloWorld
23 COMP10081 Graphical User Interfaces
HelloWorld main()
The HelloWorld constructor doesn’t do anything about displaying the window that we have created.
? Why not?
In order to make the window visible, we call ���setVisible( true ) ���This will make the window visible, and then bring it to the front.
/* Main method to drive the program */ public static void main(String [] args) {
HelloWorld theHelloWorld = new HelloWorld(); theHelloWorld.setVisible( true ); } // main
HelloWorld
24 COMP10081 Graphical User Interfaces
Coursework Task
Reimplement the HelloWorld GUI example to greet the world in French (or some other language).
25 COMP10081 Graphical User Interfaces
Layout
Our first example simply added a single component to the container. If we want to add more than one component, we need to specify how
those components should be layed out on the screen. In Swing, layout is controlled by a LayoutManager.
There are a number of different layout managers provided in the system libraries. Three simple ones are: – FlowLayout – GridLayout – BorderLayout
These are sufficient to build quite sophisticated interfaces.
26 COMP10081 Graphical User Interfaces
Example: HelloSolarSystem
Our next example is an extension of the HelloWorld program. This will make a window appear on the screen with a number of
messages. We will use a FlowLayout to control how the messages appear on
the screen. In FlowLayout, the components are simply added one after the
other, and “flow” across the screen.
HelloSolarSystem
27 COMP10081 Graphical User Interfaces
Example: HelloSolarSystem import java.awt.Container; import java.awt.FlowLayout; import javax.swing.JLabel; import javax.swing.JFrame;
public class HelloSolarSystem extends JFrame {
/* Constructor */ public HelloSolarSystem()
setTitle("Hello Solar System"); /* Get the contents of the frame and add labels to it */ Container contents = getContentPane();
/* Set the layout manager */ contents.setLayout( new FlowLayout() );
contents.add(new JLabel("Hello Mercury!")); contents.add(new JLabel("Hello Venus!")); contents.add(new JLabel("Hello Earth!")); contents.add(new JLabel("Hello Mars!")); contents.add(new JLabel("Hello Jupiter!")); contents.add(new JLabel("Hello Saturn!")); contents.add(new JLabel("Hello Uranus!")); contents.add(new JLabel("Hello Neptune!")); contents.add(new JLabel("Hello Pluto!"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); } // HelloSolarSystem
28 COMP10081 Graphical User Interfaces
HelloSolarSystem constructor
The constructor sets the layout manager for the content pane to be a new instance of FlowLayout.
/* Constructor */ public HelloSolarSystem()
setTitle("Hello Solar System"); /* Get the contents of the frame and add labels to it */ Container contents = getContentPane();
/* Set the layout manager */ contents.setLayout( new FlowLayout() );
contents.add(new JLabel("Hello Mercury!")); contents.add(new JLabel("Hello Venus!")); contents.add(new JLabel("Hello Earth!")); contents.add(new JLabel("Hello Mars!")); contents.add(new JLabel("Hello Jupiter!")); contents.add(new JLabel("Hello Saturn!")); contents.add(new JLabel("Hello Uranus!")); contents.add(new JLabel("Hello Neptune!")); contents.add(new JLabel("Hello Pluto!"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); } // HelloSolarSystem
29 COMP10081 Graphical User Interfaces
HelloSolarSystem constructor
We then add a number of labels, one for each planet. The rest of the constructor is as before. The main() method is similar.
/* Constructor */ public HelloSolarSystem()
setTitle("Hello Solar System"); /* Get the contents of the frame and add labels to it */ Container contents = getContentPane();
/* Set the layout manager */ contents.setLayout( new FlowLayout() );
contents.add(new JLabel("Hello Mercury!")); contents.add(new JLabel("Hello Venus!")); contents.add(new JLabel("Hello Earth!")); contents.add(new JLabel("Hello Mars!")); contents.add(new JLabel("Hello Jupiter!")); contents.add(new JLabel("Hello Saturn!")); contents.add(new JLabel("Hello Uranus!")); contents.add(new JLabel("Hello Neptune!")); contents.add(new JLabel("Hello Pluto!"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); } // HelloSolarSystem
HelloSolarSystem
30 COMP10081 Graphical User Interfaces
Coursework Task
In early chapters we went from HelloWorld to HelloMyFamily. In this task we do the same, but provide a GUI that greets (some
some subset of) your family. Use a FlowLayout to control the layout of the GUI.
31 COMP10081 Graphical User Interfaces
Running HelloSolarSystem
As you can see, this produces rather ugly results. ? What would happen with 100 planets?
Can we improve on this?
HelloSolarSystem
32 COMP10081 Graphical User Interfaces
Improving Layout
The FlowLayout manager simply puts all the components one after another and “flows” them across the container.
Each component takes as much space as it needs.
With lots of components, this doesn’t always produce nice looking results.
Comp1 Comp2 Comp3 Comp4 Comp5 Comp6
Components flow across Container
33 COMP10081 Graphical User Interfaces
Improving Layout: GridLayout
An alternative Layout Manager is GridLayout. GridLayout lays out components in a rectangular grid.
The grid is divided into equal sized rectangles, with each component put into one rectangle.
The grid is sized so that the biggest component will fit. – This is one of the reasons why we call pack() – to give the container a
chance to calculate all the appropriate sizes.
Comp1 Comp2 Comp3
Comp4 Comp5 Comp6
34 COMP10081 Graphical User Interfaces
HelloSolarSystemGrid
The Constructor is the same apart from the setting of the layout manager – Note that we will have to change the import headers.
/* Constructor */ public HelloSolarSystemGrid()
setTitle("Hello Solar System"); /* Get the contents of the frame and add labels to it */ Container contents = getContentPane();
/* Set the layout manager */ contents.setLayout( new GridLayout( 0, 3, 10, 10 ) );
contents.add(new JLabel("Hello Mercury!")); contents.add(new JLabel("Hello Venus!")); contents.add(new JLabel("Hello Earth!")); contents.add(new JLabel("Hello Mars!")); contents.add(new JLabel("Hello Jupiter!")); contents.add(new JLabel("Hello Saturn!")); contents.add(new JLabel("Hello Uranus!")); contents.add(new JLabel("Hello Neptune!")); contents.add(new JLabel("Hello Pluto!"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); } // HelloSolarSystem
35 COMP10081 Graphical User Interfaces
Running HelloSolarSystemGrid
Much nicer! The components are laid out in a grid as expected.
The constructor we used for GridLayout is: – GridLayout(int rows, int cols, int hgap,
int vgap)
If we supply an argument of 0 for rows or columns, this means “any number”. – So in our example, we’ve fixed the number of columns at 3 – as many
rows as necessary will be added to display all the components.
HelloSolarSystemGrid
36 COMP10081 Graphical User Interfaces
Coursework Task
Repeat, this time using a GridLayout to control the layout of the GUI. – Experiment with different values for rows and columns to see what the
effects are.
Write a program that shows a times table using a JLabel to represent each number. Use a GridLayout to control the layout.
37 COMP10081 Graphical User Interfaces
Beyond Simple Text
We’ve seen JLabel used to display a piece of text. A JLabel can also be used to display an image:
– This can help in providing more interesting GUIs.
We create a new ImageIcon object and pass that to the JLabel.
/* Get the contents of the frame and add a label to it */ Container contents = getContentPane(); contents.add(new JLabel( new ImageIcon( "smiley.jpg" ) );
HelloShark
38 COMP10081 Graphical User Interfaces
Aside: LayoutManager as a parameter
The constructors for HelloSolarSystem and HelloSolarSystemGrid are identical apart from the creation of the FlowLayout or GridLayout.
/* Constructor */ public HelloSolarSystem()
setTitle("Hello Solar System"); /* Get the contents of the frame and add labels to it
*/ Container contents = getContentPane();
/* Set the layout manager */ contents.setLayout( new FlowLayout() );
contents.add(new JLabel("Hello Mercury!")); contents.add(new JLabel("Hello Venus!")); contents.add(new JLabel("Hello Earth!")); contents.add(new JLabel("Hello Mars!")); contents.add(new JLabel("Hello Jupiter!")); contents.add(new JLabel("Hello Saturn!")); contents.add(new JLabel("Hello Uranus!")); contents.add(new JLabel("Hello Neptune!")); contents.add(new JLabel("Hello Pluto!"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); } // HelloSolarSystem
/* Constructor */ public HelloSolarSystemGrid()
setTitle("Hello Solar System"); /* Get the contents of the frame and add labels to it
*/ Container contents = getContentPane();
/* Set the layout manager */ contents.setLayout( new GridLayout( 0, 3, 10, 10 ) );
contents.add(new JLabel("Hello Mercury!")); contents.add(new JLabel("Hello Venus!")); contents.add(new JLabel("Hello Earth!")); contents.add(new JLabel("Hello Mars!")); contents.add(new JLabel("Hello Jupiter!")); contents.add(new JLabel("Hello Saturn!")); contents.add(new JLabel("Hello Uranus!")); contents.add(new JLabel("Hello Neptune!")); contents.add(new JLabel("Hello Pluto!"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); } // HelloSolarSystemGrid
We could move the creation of the layout manager out of this method and pass it in as an argument to the constructor – this would give us some extra flexibility and make it easier to experiment with other layouts.
39 COMP10081 Graphical User Interfaces
Summary
Elements of GUIs – Windows and Frames
JFrame – Components
JLabel – Containers
Extending Existing Classes – Reusing classes and adding new functionality
Layout Management – FlowLayout – GridLayout
41 COMP10081 Graphical User Interfaces
Interacting with a GUI
The HelloWorld and HelloSolarSystem examples provide GUIs that the user doesn’t really interact with. – We can’t press buttons to change the state or make the application do
anything (other than close down).
Swing provides a number of components that allow us to build interactive interfaces – E.g. Buttons to start or stop an application
The next example is a simple stop clock timer that the user can stop and start by pressing a button.
StopClock
42 COMP10081 Graphical User Interfaces
Event Driven Programming
The programs that you have seen up to now are procedural: the flow of execution is controlled by loops and decision statements. – E.g. do A, then B, then while some condition is true, do C.
This is known as procedural programming
In event driven programming, code is executed when events occur. – This is appropriate when programs need to react to external events, such
as the action of a user
43 COMP10081 Graphical User Interfaces
Event Driven Programming
A Procedural Program is like a recipe – It gives a series of instructions that are to be performed in sequence.
Making a burger: 1. Turn the grill on 2. Grill burger until cooked 3. Turn the grill off 4. Butter bun 5. Put burger on bun 6. If cheeseburger, add cheese 7. Add salad 8. Add top of bun
Of course there may be many more steps with complicated loop or control structures. – But the instructions are followed in sequence.
44 COMP10081 Graphical User Interfaces
Event Driven Programming
In the burger example, we know exactly what we’re going to do, and what’s going to happen – There’s no need to react to external events.
Consider a burger van:
Sam Larry
45 COMP10081 Graphical User Interfaces
Burgers
Larry doesn’t know what the orders are going to be at the beginning of the evening, so can’t know beforehand what he has to do.
Instead, he reacts to external events (orders) as they come in from Sam
Within the handling of each particular order, he may then follow a simple procedural path (for example, someone might order a cheese burger)
46 COMP10081 Graphical User Interfaces
Events
Java provides a rich event model: a framework for handling events. – In particular this includes libraries for events relating to GUIs.
There are many different kinds of event. Here, we will be interested in ActionEvent
ActionEvents occur when a user performs some kind of action on a GUI, for example pressing a button. – We say that the event has been raised.
Events can also represent other things: – The user typed something at the keyboard – A window has been closed – The state of an object has been changed.
47 COMP10081 Graphical User Interfaces
Sources and Listeners
In the Java Event model, actions involve at least two participants – The source produces an event, – The listener receives the event. – There is also an object that represents the event itself.
48 COMP10081 Graphical User Interfaces
Sauces and Listeners
Consider our burger van example – The customer tells Sam what she wants. – Sam shouts this out, creating an order – The order is thus passed to Larry, who (hopefully) then cooks the
appropriate food.
Sam Larry
Order Customer
Make Choices Shout Order Order to Larry
49 COMP10081 Graphical User Interfaces
Sources and Listeners
A general pattern for this is as follows
Source Object Listener Object
ActionEvent Object User Action
Trigger event
Generate event
Notify listener
Register with Source
• Note that the listener must register with the source, telling it that it is interested in receiving events.
50 COMP10081 Graphical User Interfaces
In our example, Sam is playing the role of a widget on a user interface. Widgets can be the source of events
Larry plays the role of an event listener, an object that reacts to events as they are raised.
51 COMP10081 Graphical User Interfaces
Events
In the Java Event model, events are represented as objects. This means that the object can carry around some state with it
For example, we can find out the object that caused the event to happen (the source)
? Why would we want to know about the source?
52 COMP10081 Graphical User Interfaces
Interfaces
Interfaces in Java allow us to specify particular methods that we want classes to implement. – The interface advertises the fact that instances of the class will supply
some particular methods.
A class that implements the interface then has to provide code for the methods named.
Interfaces are like protocols – They specify some agreed behaviour
53 COMP10081 Graphical User Interfaces
Implementing Interfaces
For example, the ActionListener interface has a single method: – public void actionPerformed( ActionEvent e )
If a class implements this interface, instances of the class will be able to respond in some appropriate manner when they receive ActionEvents.
Because the class implements the interface, instances can be registered as listeners with objects such as JButton, that are sources of ActionEvents.
54 COMP10081 Graphical User Interfaces
Designing the StopClock
There are (at least) two things we need to think about when designing our Stop Clock class
The information that the stop clock holds
What the clock will look like on the screen – What information do we show? – What controls will the clock have?
The two are obviously related – We can’t display information that the clock isn’t holding!
55 COMP10081 Graphical User Interfaces
Class Design
What information should the clock hold? – When it was started. – When it was stopped. – Whether it is running.
These can all be represented using instance variables.
For the first two, we can use a Date. The third is a boolean value.
56 COMP10081 Graphical User Interfaces
GUI
What should the clock look like? When building GUIs, it’s often useful to sketch something out on
paper first.
57 COMP10081 Graphical User Interfaces
StopClock instance variables
Private instance variables hold the state of the clock – isRunning, startDate, stopDate
We will display the values using labels, so we also have variables that represent the labels used on the clock, and provide them with initial values.
public class StopClock extends JFrame implements ActionListener { ... /* Local instance variables */ private boolean isRunning = false; private Date startDate; private Date stopDate; private JLabel startTimeJLabel = new JLabel( "Not started" ); private JLabel stopTimeJLabel = new JLabel( "Not started" ); private JLabel elapsedTimeJLabel = new JLabel( "Not started" ); ... }
58 COMP10081 Graphical User Interfaces
StopClock constructor
The class header tells us that the class is going to implement ActionListener.
We must then provide code for the required actionPerformed() method.
If we don’t provide the method required by the interface, the compiler will report an error.
public class StopClock extends JFrame implements ActionListener { ... public void actionPerformed( ActionEvent evt ) { ... } ... }
59 COMP10081 Graphical User Interfaces
StopClock actionPerformed()
If the clock isn’t running, start it and make a note of the start time. Otherwise, stop the clock and update the display.
public void actionPerformed( ActionEvent evt ) { if (! isRunning) { /* Start the clock */
startDate = new Date(); startTimeJLabel.setText( "" + startDate ); stopTimeJLabel.setText( "Running..." ); elapsedTimeJLabel.setText( "Running..." ); isRunning = true; // Need to pack again because label size may have changed pack();
} else { /* Stop the clock and show the updated times */ stopDate = new Date(); stopTimeJLabel.setText( "" + stopDate ); long elapsedMilliSeconds = ( stopDate.getTime() - startDate.getTime() ); elapsedTimeJLabel.setText( "" + elapsedMilliSeconds / 1000.0 ); isRunning = false; // Need to pack again because label size may have changed pack();
} } // actionPerformed
60 COMP10081 Graphical User Interfaces
Running StopClock
StopClock
61 COMP10081 Graphical User Interfaces
StopClock Sources and Listeners
What happens in the stop clock?
startStopJButton theStopClock
evt
Press Button
Generate event
Event passed to listener
startStopJButton.addActionListener( this )
When the button is pressed, a new ActionEvent object is created and passed to the StopClock object. The actionPerformed() method is then invoked with the event as argument.
actionPerformed( evt )
62 COMP10081 Graphical User Interfaces
Who calls the method?
Within our StopClock class, we defined a method actionPerformed() that was never explicitly called.
However it does get called sometime during the execution of the program if the button gets pressed.
This is a common feature of event-driven programming – The methods you write may not be called explicitly within your code.
This can make such programs – hard to debug – hard to test
But where is the method called?
63 COMP10081 Graphical User Interfaces
Threads: Parallel Execution
Consider a busy lecturer He has many things to do in a day:
– Write a paper – Mark some work – Give a lecture – Keep up with email
He can only do one thing at a time (he’s a man).
He could do one after the other, but that ���might cause problems
– Important emails may get missed – He may be writing collaboratively
Instead, he can (appear to) perform the tasks in parallel – What he’s actually doing though, is switching between them.
http://www.flickr.com/photos/teddy-rised/2814710002/
http://ww
w.flickr.com
/photos/pelegrino/3609028124/
64 COMP10081 Graphical User Interfaces
Threads: Parallel Execution
We have grown used to being able to perform many tasks “simultaneously” with computers. – Several programs running “at the same time” – What’s usually happening though is that each program has its own
process, and the resources of the central processor are shared between the processes.
– There are various strategies for dividing time between processes. – The swapping between processes is rapid enough for you not to notice
this (most of the the time)
In Java, we have the notion of threads, which allow a single program to perform a number of tasks.
65 COMP10081 Graphical User Interfaces
Threads: Main Thread
When a Java program starts, the virtual machine (VM) creates the main thread. This executes the main() method, along with any method calls there might be within the body.
When the thread reaches the end of the body, the thread terminates. – If the main thread was the only thread, then the virtual machine ends the
program. – Otherwise, the program will continue to run until all threads have
terminated.
Up to now, the programs you have been writing have had a single thread. – So the programs end when the main thread gets to the end of the main
body.
The situation is a little different when we begin to use GUI components.
66 COMP10081 Graphical User Interfaces
Threads: GUI Thread
When a program creates a window on the screen, the ���virtual machine creates a new thread -- the GUI thread.
This thread actually spends much of its time “asleep”.
When the user does something interesting (e.g. presses ���a button), the operating systems tell the VM, and the VM wakes up the GUI thread. The GUI thread then checks to see if the event really was interesting, and if so, executes the appropriate code.
Once it’s done, the GUI thread goes back to sleep again.
Note that the processor isn’t necessarily executing tasks in parallel, but will (usually) be swapping between the threads. – Again though, this is so rapid, we don’t notice this.
67 COMP10081 Graphical User Interfaces
... imports ...!
/**! * Simple frame with a single button.! * @author <a href="mailto:[email protected]">Sean Bechhofer</a>! */!public class Button extends JFrame implements ActionListener {!
private JButton theButton = new JButton( "Press Me!" );!
/* Constructor */! public Button() {!
!setTitle("One Button");!!/* Get the contents of the frame and add a label to it */!!Container contents = getContentPane();!!contents.add( theButton );!!theButton.addActionListener(this);!
!/* Specify appropriate behaviour when the window is closed */!!setDefaultCloseOperation(EXIT_ON_CLOSE);!
!/* pack the frame */!!pack();!
} // OneButton!
public void actionPerformed( ActionEvent evt ) {!!System.out.println("Pressed!");!
}!
/* Main method to drive the program */! public static void main(String [] args) {! !Button theButton = new Button();!
!theButton.setVisible( true );! } // main!
} // OneButton!
68 COMP10081 Graphical User Interfaces
Threads
Java’s system libraries provide a number of classes that allow us to explicitly create and manage threads. – What kind of issues might come up?
For the programs that we are creating, ���and for our GUI programs, we don’t ���need to worry about this, and can ���happily allow the VM to take care of our ���threading needs.
http://www.flickr.com/photos/hddod/1381966398/
69 COMP10081 Graphical User Interfaces
StopClock with a Split time
Now, we decide that we want to be able to record split times while the clock is running.
We can add a second button for this – When it is pressed, the clock continues to run, but updates to display the
value of the split time.
StopClockSplit
70 COMP10081 Graphical User Interfaces
StopClockSplit changes
We need to add another label and another button. We need to change the constructor in order to add the field and
button in the appropriate place. The first half of actionPerformed() will be (almost) the same.
71 COMP10081 Graphical User Interfaces
StopClockSplit actionPerformed()
When the clock is running, we now have a problem. The user can either press Start/Stop, to stop the clock (as before), or
can press Split to record a split time (but leave the clock running). These two actions should have different consequences.
The StopClock will be registered as a listener with both buttons, but has a single actionPerformed() method.
How do we know which button has been pressed?
72 COMP10081 Graphical User Interfaces
ActionEvent sources
As we’ve seen, in the Java Event Model, events are represented by objects.
In our example, instances of ActionEvent are used to represent actions such as the user pressing a button.
These objects carry information around with them.
So for example, we can ask an event for it’s source -- the object that caused the event to be raised. – This is done by calling the getSource() method on the event object.
In our example, the source of the event object will be the JButton that was pressed.
This then allows us to check which button was pressed, and take appropriate action.
73 COMP10081 Graphical User Interfaces
Running StopClockSplit
StopClockSplit
74 COMP10081 Graphical User Interfaces
Coursework Task
Take the StopClock example and change the code to provide a split time button.
When the split time button is pressed, the clock should continue to run but the split or elapsed time should be displayed.
The split button can be pressed any number of times when the clock is running, with the elapsed time updating each time it is pressed.
75 COMP10081 Graphical User Interfaces
Summary
Events and the Java Event Model – Event Sources – Event Listeners
Implementing Interfaces – ActionListener
Multiple sources, one listener – ActionEvent
Threads
77 COMP10081 Graphical User Interfaces
Interacting with a GUI
In our previous example, we provided the user with the opportunity to interact with a GUI by pressing buttons.
Up to now, the only way that we’ve been able to pass information or data into a program has been via arguments to main().
Now we’re going to add components to an interface that allow the user to enter data.
Our example will be an interface to the GCD code that we have already seen.
78 COMP10081 Graphical User Interfaces
JTextField
Our new GUI will allow the user to enter some data – This is done using text fields.
JTextField is a component that displays some text.
Unlike JLabel, however, the user can interact with the text field and can enter new values.
79 COMP10081 Graphical User Interfaces
GCD instance variables
We have three text fields that will hold the text to be displayed. When creating a text field we can specify how big it should be – this
then allows the interface to size itself appropriately. – The field will start off with an empty string as content.
It’s also possible to provide a JTextField with some initial value:
public class GCD extends JFrame implements ActionListener { ... private JTextField number1JTextField = new JTextField( 20 ); private JTextField number2JTextField = new JTextField( 20 ); private JTextField resultJTextField = new JTextField( 20 ); ... }
JTextField myField = new JTextField( "hello" );
80 COMP10081 Graphical User Interfaces
GCD constructor
The text fields are added to the GUI just like any other components.
public GCD() { setTitle("GCD"); Container contents = getContentPane(); contents.setLayout( new GridLayout( 0, 1 ) ); contents.add( new Label( "Number 1" ) ); contents.add( number1JTextField ); contents.add( new Label("Number 2" ) ); contents.add( number2JTextField ); JButton computeJButton = new JButton( "Compute" ); contents.add( computeJButton ); computeJButton.addActionListener( this ); contents.add( new Label( "GCD of Number 1 and Number 2" ) ); contents.add( resultJTextField ); /* Specify appropriate behaviour when the window is closed */ setDefaultCloseOperation( EXIT_ON_CLOSE );
pack(); } // GCD
81 COMP10081 Graphical User Interfaces
GCD actionPerformed()
In actionPerformed(), we can get the values that the user has entered into the text fields, and then compute the GCD based on those values.
Note that as the result of getText() is a String, we need to parse the string to an int before we can process it. – This is similar to the original example where the arguments were passed
in from the command line
Once we’ve calculated the GCD, we can then set the value of the result field.
public void actionPerformed(ActionEvent e) { int number1 = Integer.parseInt( number1JTextField.getText() ); int number2 = Integer.parseInt( number2JTextField.getText() ); int theGCD = greatestCommonDivisor( number1, number2 ); resultJTextField.setText( "" + theGCD );
} // actionPerformed
82 COMP10081 Graphical User Interfaces
Running GCD
GCD
83 COMP10081 Graphical User Interfaces
Coursework Task
Provide a GUI that allows you to input three numbers and calculate their GCD.
84 COMP10081 Graphical User Interfaces
Enabling and Disabling Components
Components like buttons and text fields allow the user to interact with them – We can press buttons or enter text into text fields
Sometimes in a GUI we might want to disable a component. For example, in a mailer, we might not want the user to be able to
send a message unless a valid mail address has been entered into the To: field.
We could do this by: – Allowing the user to press the Send button, but raising an error if the
mail address is invalid – Disabling the Send button until a valid mail address has been given.
Java Components can be enabled and disabled through the setEnabled( boolean ) method.
85 COMP10081 Graphical User Interfaces
Disabling Text Fields
In our GCD example, it doesn’t make any sense for the user to be able to type text into the result field.
We can prevent this happening by disabling it.
? A disabled JTextField seems a bit like a JLabel. Why have both?
GCDDisabled
86 COMP10081 Graphical User Interfaces
Coursework Task
Reimplement StopClock with a split time making the following changes: – Use JTextField instead of JLabel to display the start/stop date and
elapsed time.
– Change the behaviour of the split time button so that it is disabled when the clock isn’t running.
87 COMP10081 Graphical User Interfaces
JTextArea
A JTextField is good for input or display of a single line of text. If we want to display more than one line, a JTextArea is
appropriate. An example using a JTextArea is an application that displays a
times table.
88 COMP10081 Graphical User Interfaces
TimesTable instance variables
The TimesTable GUI has a single text field for input of a value, and a text area to display the results of calculating the table.
When we create a text area, we say how many rows and columns we expect it to have – again as with the text fields, this allows the layout manager to work out how much space it should give the text area.
public class TimesTable extends JFrame implements ActionListener { ... private JTextField multiplierJTextField = new JTextField( 5 ); private JTextArea displayJTextArea = new JTextArea( 15, 20 ); ... }
89 COMP10081 Graphical User Interfaces
BorderLayout
The TimesTable GUI is going to use a third layout manager that we haven’t yet seen – BorderLayout.
This is slightly more complicated than FlowLayout and GridLayout, but provides more flexibility.
Combinations of FlowLayout, GridLayout and BorderLayout will allow us to build quite sophisticated interfaces.
90 COMP10081 Graphical User Interfaces
BorderLayout
In BorderLayout, the container is divided into five areas: – North, South, East, West and Center
When we add a component to a container that’s using a BorderLayout, we say which area we want the component to appear in: – Constants from the BorderLayout class are used to indicate this.
contents.add( myComponent, BorderLayout.NORTH )
Center West East
North
South
91 COMP10081 Graphical User Interfaces
TimesTable constructor
The constructor is similar to those we’ve seen before, but here, when we add the components, we tell the layout manager which area of the layout we want them to appear in. – Order is no longer important. We could add the button first and it
would still appear at the bottom of the screen.
– With BorderLayout we have to be careful that we don’t add two components to the same area.
public TimesTable() { setTitle("Times Table"); Container contents = getContentPane(); contents.setLayout(new BorderLayout()); contents.add( multiplierJTextField, BorderLayout.NORTH ); contents.add( displayJTextArea, BorderLayout.CENTER ); JButton displayJButton = new JButton( "Display“ ); contents.add( displayJButton, BorderLayout.SOUTH ); displayJButton.addActionListener( this ); pack();
} // TimesTable
92 COMP10081 Graphical User Interfaces
TimesTable actionPerformed()
In actionPerformed(), the first thing we do is clear the text area by using setText() to set it to be the empty string. – setText() will replace any existing text.
We can then append text to the text area using append(). – This doesn’t replace the area, but adds the text on to the end.
We can include new lines in the text by including the newline character "\n".
public void actionPerformed( ActionEvent e ) { displayJTextArea.setText( "" ); int multiplier = Integer.parseInt( multiplierJTextField.getText() ); displayJTextArea.append( "--------------------------------\n" ); displayJTextArea.append( "| Times table for " + multiplier + "\n" ); displayJTextArea.append( "--------------------------------\n" ); for (int thisNumber = 1; thisNumber <= 10; thisNumber = thisNumber + 1) displayJTextArea.append( "| " + thisNumber + " x " + multiplier + " = " + thisNumber * multiplier + "\n" ); displayJTextArea.append( "--------------------------------\n" );
} // actionPerformed
93 COMP10081 Graphical User Interfaces
TimesTable actionPerformed()
A for loop is used to append the times table to the text area.
public void actionPerformed( ActionEvent e ) { displayJTextArea.setText( "“ ); int multiplier = Integer.parseInt( multiplierJTextField.getText() ); displayJTextArea.append( "--------------------------------\n" ); displayJTextArea.append( "| Times table for " + multiplier + "\n" ); displayJTextArea.append( "--------------------------------\n" ); for ( int thisNumber = 1; thisNumber <= 10; thisNumber = thisNumber + 1 ) displayJTextArea.append( "| " + thisNumber + " x " + multiplier + " = " + thisNumber * multiplier + "\n" ); displayJTextArea.append( "--------------------------------\n" );
} // actionPerformed
94 COMP10081 Graphical User Interfaces
Running TimesTable
TimesTable
95 COMP10081 Graphical User Interfaces
JPanel: Building things up from pieces
So far, all our interfaces have been relatively simple. We’ve been able to use a single container to hold the pieces that we wanted.
Often, however, our interfaces will be made up of a number of different parts or panels, that we want to combine together into one big piece. – For example, think of Mozilla’s mail interface.
In this case, having a single container and layout manager won’t be enough.
Java provides a lightweight container known as JPanel that allows us to do build things up. – A JPanel is a blank area that we can add things to. – The JPanel can then be added to other containers.
96 COMP10081 Graphical User Interfaces
GCDWithPanels constructor
In the constructor, we build a number of different instances of JPanel. Each one has its own layout manager, and panels can then be added to other panels or the contents of the JFrame.
Note that the order in which we add things here doesn’t matter. – The panel is added to the container before the labels and fields are added to the
panel. – Calling pack() at the end of the constructor makes sure that everything gets
sized properly.
public GCDWithPanels() { setTitle("GCD"); Container contents = getContentPane(); contents.setLayout(new GridLayout(0, 1));
JPanel numberFieldsPanel = new JPanel(); numberFieldsPanel.setLayout( new GridLayout( 0, 2 ) ); contents.add( numberFieldsPanel );
numberFieldsPanel.add( new JLabel( "Number 1" ) ); numberFieldsPanel.add( new JLabel( "Number 2" ) ); numberFieldsPanel.add( number1JTextField ); numberFieldsPanel.add( number2JTextField );
... } // GCDWithPanels
97 COMP10081 Graphical User Interfaces
Running GCDWithPanels
GCDWithPanels
98 COMP10081 Graphical User Interfaces
Anatomy of GCDWithPanels
resultPanel with a 1-column grid layout buttonAndResultPanel
with a 2-column grid layout. Note that the Compute button is the same size as the combined label and field on the right hand side
numberFieldsPanel with a 2-column grid layout
contents with a 1-column grid layout
99 COMP10081 Graphical User Interfaces
Information Overload!
In our TimesTable example, we created a JTextArea that was big enough for the text that we wanted to display:
? What happens if we put more than 15 lines of text into this?
We can test this by changing the interface. We add a field that allows the user to input the size of table required and then change the termination condition of the for loop.
private JTextArea displayJTextArea = new JTextArea( 15, 20 );
int tableSize = Integer.parseInt(tableSizeJTextField.getText()); for ( int thisNumber = 1;
thisNumber <= tableSize; thisNumber = thisNumber + 1 ) displayJTextArea.append( "| " + thisNumber + " x " + multiplier + " = " + thisNumber * multiplier + "\n" );
private JTextField tableSizeJTextField = new JTextField(5);
100 COMP10081 Graphical User Interfaces
Running TimesTable
Once the text area is “full”, the text gets lost and doesn’t appear on the screen.
We can move the cursor off the bottom, but we still ���can’t see anything.
A solution to this is to use a Scroll Bar. TimesTable2
101 COMP10081 Graphical User Interfaces
Scroll Bars
Scroll Bars are often used in windowing applications when components are too big to fit into the available space.
They serve a number of purposes: – They allow the user to navigate (scroll) the area to find the right place – They provide an indication of where we are in the text – They give an indication of how much text is hidden – the smaller the bar,
the smaller the proportion of the text that is being shown.
102 COMP10081 Graphical User Interfaces
Scroll Bars This scrollbar is telling me that I’m at the top of the text and I’m seeing around 10% of what there is.
103 COMP10081 Graphical User Interfaces
JScrollPane
JScrollPane is a component that provides a scrollable wrapper around a component.
If the component will fit into the available space, then (by default) nothing happens and no scroll bars are shown.
If the component is too big, the JScrollPane will provide scrollbars that allow you to see all the text.
104 COMP10081 Graphical User Interfaces
TimesTableScroll constructor
The constructor is the same as before, except this time we create a new JScrollPane containing the JTextField and add that to the contents.
public TimesTableScroll() { ... contents.add( multiplierJTextField, BorderLayout.NORTH ); contents.add( new JScrollPane( displayJTextArea ), BorderLayout.CENTER ); ...
} // TimesTableScroll
105 COMP10081 Graphical User Interfaces
Running TimesTableScroll
Now we can scroll down to see all the results of the table.
TimesTableScroll
106 COMP10081 Graphical User Interfaces
Coursework Task
Implement a GUI that gives an interface to the “Three Weights” problem that you saw in Chapter 3.
The GUI should allow you to enter three values for the weights, and will then display in a text area the possible weights that could be measured using the given values.
107 COMP10081 Graphical User Interfaces
Containment Hierarchies
Containers like JPanel allow us to build up nested collections of components.
In order to appear on the screen, every GUI component must be part of a containment hierarchy. A containment hierarchy is a tree of components that has an instance of a Top Level Container (such as JFrame) as its root.
108 COMP10081 Graphical User Interfaces
Summary
Components for displaying and entering text – JTextField – JTextArea
More sophisticated layout management – BorderLayout
Building up interfaces in pieces – JPanel – JScrollPane
110 COMP10081 Graphical User Interfaces
More than one Window
So far, all our programs have used a single window (or frame) This doesn’t have to be the case
– We can have a number of different windows open at the same time.
To demonstrate this, we’ll extend our GCD example to allow the user to open up another window.
GCDWithNew
111 COMP10081 Graphical User Interfaces
GCDWithNew changes
As with the StopClock example, we add a new button to the window.
The class is changed to add buttons as instance variables
We also change the constructor to add the button to the screen and register the GCDWithNew object with the button as a listener.
112 COMP10081 Graphical User Interfaces
GCDWithNew actionPerformed()
The code computing the GCD is the same. However, this is only executed if the Compute button was pressed.
If the New button is pressed, we create a new object and then ask it to display on the screen. – Recall that the constructor doesn’t make the window display.
public void actionPerformed(ActionEvent e) { if ( e.getSource() == computeJButton ) {
int number1 = Integer.parseInt(number1JTextField.getText()); int number2 = Integer.parseInt(number2JTextField.getText()); int theGCD = greatestCommonDivisor(number1, number2); resultJTextField.setText("" + theGCD);
} else if ( e.getSource() == newJButton ) { GCDWithNew newOne = new GCDWithNew(); newOne.setVisible( true ); } } // actionPerformed
113 COMP10081 Graphical User Interfaces
Running GCDWithNew
GCDWithNew
114 COMP10081 Graphical User Interfaces
Problem I
The new window opens up directly on top of the old one. This is because we haven’t said anything about where we expect the
window to appear By default the window appears in the top left hand corner
A solution would be to tell the new window that it should open up in a slightly different place.
115 COMP10081 Graphical User Interfaces
Locations
We can solve this problem by: – Getting the location of the current window – Setting the location of the new window to be a position relative to the
location of the current window.
We can get the location of a window using method:
We can set the location of a window using method:
Point is a class from the Java libraries that ���represents a pair of (x, y) coordinates.
public Point getLocation()
public void setLocation( Point p )
GCDWithNew2
116 COMP10081 Graphical User Interfaces
Problem II
What happens when we close one of the windows? All of the windows disappear and the program exits.
This is exactly how we told the application to behave!
This means that the application terminates when any of the windows are closed.
? Why might this be a problem?
public GCDWithNew2() { ... /* Specify appropriate behaviour when the window is closed */ setDefaultCloseOperation( EXIT_ON_CLOSE );
... } // GCDWithNew
117 COMP10081 Graphical User Interfaces
Setting the Default Close Operation
In our code we have been using EXIT_ON_CLOSE as the default action.
This means that the entire application quits
An alternative is to use DISPOSE_ON_CLOSE
This means that the window will be hidden, then the object representing the frame will be disposed of.
If we do this, it means that when one window is closed, the application will continue to run, and other windows will still be there.
/* Specify appropriate behaviour when the window is closed */ setDefaultCloseOperation( DISPOSE_ON_CLOSE );
GCDWithNew3
118 COMP10081 Graphical User Interfaces
When does the application terminate?
With the use of EXIT_ON_CLOSE, we can be sure that the application will terminate when a window is closed.
With DISPOSE_ON_CLOSE, as long as we have been careful about the creation of our windows and listener objects, the application will terminate when all the windows have been closed. – The GUI thread(s) will terminate and the virtual machine will end the
program. – Recall our earlier discussion of threads
119 COMP10081 Graphical User Interfaces
A Simple Log Book application
Your logbook is used to record information as you work. In this example, we provide a GUI where messages can be typed into
a window and then collected together in a single log. We can open separate windows for different “tasks”.
The GUI has: – A field for a label – A text area for the message – Buttons for Log and New actions.
LogGUI
120 COMP10081 Graphical User Interfaces
LogBook
The LogBook has a name There is also an instance of SimpleDateFormat
– This is a helper class from the Java libraries that can print out Date objects in a nice way.
import java.text.SimpleDateFormat; import java.util.Date;
/** A class that records information. */ public class LogBook {
private String logName; private String log;
private SimpleDateFormat dateFormat;
/* Constructor */ public LogBook( String aLogName ) {
logName = aLogName; dateFormat = new SimpleDateFormat( "hh:mm:ss" );
log = ""; }
... }
121 COMP10081 Graphical User Interfaces
LogBook
There is a method on LogBook that can be called when somebody wants to log a message. – The method takes a label and the message.
The message is printed out to the console along with the time.
/** Log a message. */ public void logMessage( String label,
String message ) { Date now = new Date();
String logMessage = "Time: " + dateFormat.format( now ) + "\n" + "Label: " + label + "\n"+ "Note: " + message;
/* Add the message to the log */ log = log + logMessage + "\n";
/* Display the message */ System.out.println( "-------------------------------" ); System.out.println( logMessage ); System.out.println( "-------------------------------" );
}
122 COMP10081 Graphical User Interfaces
LogGUI
LogGUI provides us with a window where we can log messages. An instance of LogGUI has a reference to a LogBook
– This is passed in to the constructor.
public class LogGUI extends JFrame implements ActionListener { ... /* The LogBook that we will send messages to */ private LogBook logBook;
public LogGUI( LogBook aLogBook ) { logBook = aLogBook; ... } // LogGUI ... }
123 COMP10081 Graphical User Interfaces
LogGUI
public void actionPerformed( ActionEvent e ) { if ( e.getSource() == logButton ) { /* Log the message */ logBook.logMessage( labelField.getText(), messageTextArea.getText() ); /* Now clear the text */ messageTextArea.setText(""); } else if ( e.getSource() == newButton ) { /* Create a new GUI with the same logBook */ LogGUI newLogGUI = new LogGUI( logBook ); newLogGUI.setVisible( true ); }
} // actionPerformed
If the Log button is pressed, then the text that has been typed into the text area is passed to the room object’s logMessage() method. – This will result in the message being printed out on the console.
• We then clear the text area ready for the next message.
124 COMP10081 Graphical User Interfaces
If the New button is pressed, then we create a new instance of LogGUI, but pass in the same LogBook instance.
This means that any messages sent from the new window will be sent to the same LogBook instance.
LogGUI
public void actionPerformed( ActionEvent e ) { if ( e.getSource() == logButton ) { /* Log the message */ logBook.logMessage( labelField.getText(), messageTextArea.getText() ); /* Now clear the text */ messageTextArea.setText(""); } else if ( e.getSource() == newButton ) { /* Create a new GUI with the same logBook */ LogGUI newLogGUI = new LogGUI( logBook ); newLogGUI.setVisible( true ); }
} // actionPerformed
LogGUI
125 COMP10081 Graphical User Interfaces
Multiple GUIs, one object
What we’re seeing here is a situation where we have more than one window or GUI manipulating a single object, sometimes referred as the model.
We’re also seeing that the ���state of the GUI may be held���indirectly by other objects
It does not necessarily have ���to be held as direct instance ���variables of the GUI class ���itself.
LogBook
LogGUI LogGUI
126 COMP10081 Graphical User Interfaces
Separate Listeners
So far, whenever we have used an ActionListener, it has been the JFrame object that has responded to the ActionEvents.
This doesn’t have to be the case.
Anything can be an ActionListener, as long as it implements the appropriate methods.
We demonstrate this by changing the way that our log book application works.
Rather than printing out the messages to standard output, the log book stores all the messages in a String variable.
We add an additional button to the GUI that causes the ���log book to print all the messages to standard output.
LogGUI2
127 COMP10081 Graphical User Interfaces
LogGUI2
In LogGUI2 we add another button. This time, rather than adding the JFrame (this) as an
ActionListener, we add the logBook object which was passed in to the constructor as the listener.
public class LogGUI2 extends JFrame implements ActionListener {
... private JButton transcriptButton = new JButton("Transcript"); ... public LogGUI2( LogBook2 aLogBook ) { ... buttonPanel.add( transcriptButton ); transcriptButton.addActionListener( aLogBook ); ... } // LogGUI2 }
128 COMP10081 Graphical User Interfaces
LogBook2
In order to make sure that instances of LogBook2 can respond to ActionEvents, we need to supply the actionPerformed() method.
We also advertise the fact that the LogBook2 class provides this method so the compiler knows that it is appropriate to register instances of this class as listeners.
Note that our LogBook2 class is not a JFrame.
public class LogBook2 implements ActionListener { ... public void actionPerformed( ActionEvent e ) { System.out.println("========================"); System.out.println( log ); System.out.println("========================"); } }
LogGUI2
129 COMP10081 Graphical User Interfaces
Summary
Spawning new windows Getting and setting locations
Window closing actions – Exit application – Dispose of window
Multiple GUIs, one object
One event source, many listeners.
130 COMP10081 Graphical User Interfaces
Overall Summary
The last four lectures have introduced a number of new concepts and language features.
How we can reuse and extend library classes to provide our own specialised classes.
How to build simple user interfaces using components like text fields and text areas.
How to organise components on the screen using layout managers and panels.
A brief introduction to the notion of event driven programming and examples of how to use events, sources and listeners to provide action buttons on interfaces.
Top Related