| CSCI A201/A597 Lecture Notes Twenty-Three
Second Summer 2000
|
Add user interface components to a frame. Pages 414-423, 479-488.
|
Let's start from the standalone application that we developed yesterday.
|
The one with the frame?
|
import javax.swing.*;
import java.awt.event.*;
class MyFrame extends JFrame {
public MyFrame() {
final int DEFAULT_WIDTH = 300;
final int DEFAULT_HEIGHT = 300;
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
WindowCloser w = new WindowCloser();
addWindowListener(w);
}
}
class FrameTest {
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.setTitle("This is my title.");
f.show();
}
}
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
|
You've changed a few things.
|
Not much, just the name of a class.
|
|
And the name of the constructor, in all the invocations.
|
Yes. Then I put this in a file called One.java, compiled it and
run the class with the main method in it.
|
|
OK, now let's add a few user interface components to this frame.
|
We'll add a drawing surface and a text field.
|
|
Thus illustrating the same scheme of event-handling that we presented yesterday.
|
Same scheme, different event sources.
|
|
Yes, but the mechanism is the same:
|
... define a listener, create it, register it with the source.
|
|
Then wait for the user.
|
The user is always right.
|
|
Let's first deal with the drawing surface.
|
You should never draw directly onto the surface of a frame.
|
|
Frames have been designed to arrange user interface components,
such as buttons, menus, scroll bars, and so on.
|
Drawing directly on the frame interferes with the display of the user interface components.
|
|
If you want to show graphics in a frame, you draw the graphics onto a separate component,
|
... and add that component to the frame.
|
The Swing user interface toolkit provides a special component,
called JPanel, just for this purpose.
|
A JPanel is completely blank, and you can
draw onto it what you like.
|
|
Drawing on a panel is a bit different from drawing
on an applet.
|
To draw on an applet, you override the paint method.
|
To draw on a JPanel you instead override the paintComponent method.
|
There is a second important difference;
|
... when implementing your own paintComponent method,
you must call the paintComponent method of the superclass.
|
This gives the superclass method a chance to erase the old contents of the panel.
|
|
Can you quickly remind me why we are doing all this?
|
This what?
|
|
All this GUI and event-handling thing.
|
To motivate you to study inheritance.
|
|
When will we study inheritance (also known as the
class extension mechanism)?
|
In A202. Or on our own.
|
|
If we had started with inheritance and spent a week on it,
it may have looked a bit too abstract at first, no impetus.
|
But now we see all of Java is built this way, so if we do
understand the class extension mechanism we will be in much
better shape.
|
|
Better positioned to understand the whole shebang.
|
The whole contrivance.
|
Very good. Here's an outline of the paintComponent method.
| |
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class MyFrame extends JFrame {
public MyFrame() {
final int DEFAULT_WIDTH = 300;
final int DEFAULT_HEIGHT = 300;
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
WindowCloser w = new WindowCloser();
addWindowListener(w);
}
}
class FrameTest {
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.setTitle("This is my title.");
f.show();
}
}
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// ... drawing instructions
}
}
|
As always.
|
To add a panel to a JFrame
you need to know more about the structure of
the frame surface.
|
|
The surface of a swing frame is covered with
four panes, but I can't remember what they are.
|
- Root Pane
- Layered Pane
- Menu Bar
- Content Pane
- Glass Pane
|
|
I will never remember that.
|
You don't need to. Make a note of it.
|
|
Three of them aren't even of interest, to most Java programmers.
|
Yes, but you need to know about the
content pane which holds the
components that you want to display in
the window.
|
|
OK, here's a picture of this:
| |
(e) is transparent and captures mouse events.
|
(b) holds (c) and (d) together.
|
(a) holds (e) and (b) together.
| Yes, that's it. To add a component, |
|
... such as a panel or a button,
|
... to the content pane of a frame,
|
|
... you must first get a reference to the content pane
object
|
... by calling the getContentPane method.
|
The method returns a reference of type Container.
|
A Container is a window object
that can contain other components.
|
Then you use the add method of the
Container class to add your component.
|
You need to specify both the component that you want to add,
|
|
... such as the pane,
|
... and the location where you want to add this component.
|
The content pane uses a border layout to arrange its components.
|
You specify locations in a border layout as one of the five strings:
-
"Center"
-
"North"
-
"South"
-
"East" or
-
"West"
|
|
In chapter 12 you will see how to create other layouts.
|
For now let's see how we put a panel into the "Center" are of the content pane.
|
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class MyFrame extends JFrame {
public MyFrame() {
final int DEFAULT_WIDTH = 300;
final int DEFAULT_HEIGHT = 300;
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
WindowCloser w = new WindowCloser();
addWindowListener(w);
MyPanel panel = new MyPanel();
Container contentPane = getContentPane();
contentPane.add(panel, "Center");
}
}
class FrameTest {
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.setTitle("This is my title.");
f.show();
}
}
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// ... drawing instructions
}
}
|
If you compile and run it now you won't see much of a difference.
|
Let's add a text field to the frame then and read what the user types in it.
|
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class MyFrame extends JFrame {
JTextField textField;
public MyFrame() {
final int DEFAULT_WIDTH = 300;
final int DEFAULT_HEIGHT = 300;
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
WindowCloser w = new WindowCloser();
addWindowListener(w);
MyPanel panel = new MyPanel();
Container contentPane = getContentPane();
contentPane.add(panel, "Center");
textField = new JTextField();
contentPane.add(textField, "South");
}
}
class FrameTest {
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.setTitle("This is my title.");
f.show();
}
}
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// ... drawing instructions
}
}
| |
Now it looks much better and you can even type in the text field.
|
|
Let's add a listener that processes the user input.
|
When the user hits the Enter key inside the text field
the text field generates an action event.
|
|
Listening to an action event is a simpler task than listening to a mouse
|
... because the ActionListener interface has a single method:
|
public void actionPerformed(ActionEvent e);
|
Which the listener is supposed to implement.
|
The ActionEvent tells you which component
sent the event and what kind of action the user wants to
have carried out.
|
|
You will see many examples of action events in chapter 12.
|
Right now we can ignore the contents of the event because we
know it can only come from a single component, namely the textfield.
|
|
Can't the panel send action events?
|
No, action events are sent only by buttons,
lists, menu items, and text fields
(see here).
|
|
As before we need to install a listener.
|
We therefore
define,
create,
and register it with the event source.
|
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.event.*;
class MyFrame extends JFrame {
JTextField textField;
public MyFrame() {
final int DEFAULT_WIDTH = 300;
final int DEFAULT_HEIGHT = 300;
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
WindowCloser w = new WindowCloser();
addWindowListener(w);
MyPanel panel = new MyPanel();
Container contentPane = getContentPane();
contentPane.add(panel, "Center");
textField = new JTextField();
contentPane.add(textField, "South");
TextFieldListener listener = new TextFieldListener();
textField.addActionListener(listener);
}
}
class FrameTest {
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.setTitle("This is my title.");
f.show();
}
}
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// ... drawing instructions
}
}
class TextFieldListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("The user has pressed enter in the text field.");
}
}
|
So at this point we can detect when
|
... but not what
|
|
... the user has typed inside the text field.
|
How do we get the contents of the text field?
|
|
How do we get the text field itself?
|
We have two options: we can define the listener as
an inner class as described in the book or,
|
|
... or use the action event to get to its source.
|
Let's use the second method.
|
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.event.*;
class MyFrame extends JFrame {
JTextField textField;
public MyFrame() {
final int DEFAULT_WIDTH = 300;
final int DEFAULT_HEIGHT = 300;
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
WindowCloser w = new WindowCloser();
addWindowListener(w);
MyPanel panel = new MyPanel();
Container contentPane = getContentPane();
contentPane.add(panel, "Center");
textField = new JTextField();
contentPane.add(textField, "South");
TextFieldListener listener = new TextFieldListener();
textField.addActionListener(listener);
}
}
class FrameTest {
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.setTitle("This is my title.");
f.show();
}
}
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// ... drawing instructions
}
}
class TextFieldListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
System.out.println("Textfield: " + ((JTextField)obj).getText());
}
}
|
Oh, no -- inheritance again!
|
Yes, we need to study it.
|
Last updated: July 27, 2000 by Adrian German for A201