1.124 Lecture 13 | 10/24/2000 |
In general, a graphical program consists of the following key elements:
while (true) {
// The event loop.
// Get the next event
from the event queue.
Event e = get_next_event();
// Process the events
by calling appropriate event handlers.
if (e.eventType == QUIT)
{
exit();
// Terminate the program.
}
else if (e.eventType
== BUTTON_PUSHED) {
if (e.eventSource == PRINT_BUTTON)
print(e);
// Print out the current page.
else {
...
}
}
else {
...
}
}
In C++, the programmer must often explicitly write an event loop similar
to the one shown above. This can involve a lot of work, so Java attempts
to shield the programmer from the actual event loop, while still providing
a flexible way to specify how events are processed.
The Java event model is based on the notion of event sources and event listeners.
Here is a list of events, and their corresponding event types and event listener interfaces.
Event | Event Type | Event Listener Interface |
---|---|---|
Button click, menu selection, text field entry | ActionEvent | ActionListener |
Resizing, moving, showing or hiding a component | ComponentEvent | ComponentListener |
Mouse press, mouse release, mouse click, mouse enter, mouse exit | MouseEvent | MouseListener |
Mouse move, mouse drag | MouseEvent | MouseMotionListener |
Key press, key release | KeyEvent | KeyListener |
Gain keyboard focus, lose keyboard focus | FocusEvent | FocusListener |
Window closing, window iconified, window deiconified | WindowEvent | WindowListener |
Scrolling | AdjustmentEvent | AdjustmentListener |
Item selection e.g. checkbox, list item | ItemEvent | ItemListener |
Return key pressed | TextEvent | TextListener |
Adding/removing a component to/from a container | ContainerEvent | ContainerListener |
The general approach to implementing an event listener is the same in every case.
import javax.swing.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
// Create a window.
Then set its size and make it visible.
JFrame frame = new JFrame("Main
window");
frame.setSize(400,400);
frame.setVisible(true);
// Make the program terminate
when the frame is closed. We do this by registering a window listener
// to receive WindowEvents
from the frame. The window listener will provide an event handler
called
// windowClosing, which
will be called when the frame is closed.
WindowListener listener
= new MyWindowListener();
// A class that we write.
frame.addWindowListener(listener);
}
}
// Here is our window listener. We are only interested in windowClosing,
however, we must provide
// implementations for all of the methods in the WindowListener
interface.
class MyWindowListener implements WindowListener {
public void windowClosing(WindowEvent e) {
System.out.println("Terminating
the program now.");
System.exit(0);
}
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e)
{}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e)
{}
}
Unfortunately, this example involves quite a lot of code. There
are a couple of ways to simplify the program
import javax.swing.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
// Create a window.
Then set its size and make it visible.
JFrame frame = new JFrame("Main
window");
frame.setSize(400,400);
frame.setVisible(true);
// Make the frame closable.
Here we have used an anonymous class that implements the
// WindowListener interface.
frame.addWindowListener(new
WindowListener() {
public void windowClosing(WindowEvent e) {
System.out.println("Terminating the program now.");
System.exit(0);
}
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
});
}
}
import javax.swing.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
// Create a window.
Then set its size and make it visible.
JFrame frame = new JFrame("Main
window");
frame.setSize(400,400);
frame.setVisible(true);
// Make the frame closable.
Here we have used an anonymous class that extends WindowAdapter.
frame.addWindowListener(new
WindowAdapter() {
public void windowClosing(WindowEvent e) { // This overrides
the empty base class method.
System.out.println("Terminating the program now.");
System.exit(0);
}
});
}
}
A Container is a GUI component that can hold other GUI components. Three commonly used container classes are
myContainer.getContentPane().add(myComponent);
The following example illustrates how to add a JButton instance to an instance of JFrame.
import javax.swing.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
// Create a window.
JFrame frame = new JFrame("Main
window");
frame.setSize(400,400);
// Create a button and
add it to the frame.
JButton button = new
JButton("Click me");
frame.getContentPane().add(button);
// Add an event handler
for button clicks.
button.addActionListener(new
ActionListener() {
public void actionPerformed(ActionEvent e) {
// Only one method to implement.
System.out.println(e.getActionCommand()); // Prints
out "Click me".
}
});
// Make the frame closable.
frame.addWindowListener(new
WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// Make the frame visible
after adding the button.
frame.setVisible(true);
}
}
Our previous example has only one interesting GUI component: a JButton. What if we wanted to add a second JButton and perhaps a JTextArea, so that we can display the message through the GUI? We can control the layout of these components within the container by using a layout manager. Java comes with six layout managers (five in java.awt and one in javax.swing)
public void setLocation(int x, int y)
Suppose we wish to position our two JButtons side by side, with
the JTextArea positioned below them. We start by embedding
the JButtons within a JPanel, using FlowLayout as
the layout manager for the JPanel. The JTextArea is
best placed within a JScrollPane, since this will permit scrolling
when the amount of text exceeds the preferred size of the scroll pane.
We can now attach the JPanel and the JScrollPane to the North
and South borders of the JFrame, by using BorderLayout as
the layout manager for the JFrame. These containment relationships
are illustrated below:
JFrame
|
Here is the implementation:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
// Create a window and
set its layout manager to be BorderLayout.
// (This happens to be
the default layout manager for a JFrame.)
JFrame frame = new JFrame("Main
window");
frame.setSize(400,400);
Container cf = frame.getContentPane();
cf.setLayout(new BorderLayout());
// Create a panel and
set its layout manager to be FlowLayout.
// (This happens to be
the default layout manager for a JPanel.)
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
// No content pane for JPanel.
// Create two buttons
and add them to the panel.
JButton button1 = new
JButton("Left");
JButton button2 = new
JButton("Right");
panel.add(button1);
panel.add(button2);
// Create a text area
for displaying messages. We embed the text
// area in a scroll pane
so that it doesn't grow unboundedly.
JTextArea textArea =
new JTextArea();
JScrollPane scrollPane
= new JScrollPane(textArea);
scrollPane.setPreferredSize(new
Dimension(400, 100));
textArea.setEditable(false);
// Position the panel
and the text area within the frame.
cf.add(panel, "North");
cf.add(scrollPane, "South");
// Add event handlers
for button clicks.
class MyListener implements
ActionListener { // A local class.
private JTextArea mTextArea;
public void setTextArea(JTextArea t) {
mTextArea = t;
}
public void actionPerformed(ActionEvent e) {
mTextArea.append(e.getActionCommand()+"\n");
}
}
MyListener listener =
new MyListener();
listener.setTextArea(textArea);
// Cannot do this with an anonymous class.
button1.addActionListener(listener);
button2.addActionListener(listener);
// Make the frame closable.
frame.addWindowListener(new
WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// Make the frame visible
after adding the components to it.
frame.setVisible(true);
}
}
The following link is a useful reference on using layout managers.
http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html
The components that we have seen so far are JFrame, JPanel, JButton, JTextArea and JScrollPane. The links below provide a good overview of the Swing components and how to use them.