Unit - IV Event handling using Abstract Window Toolkit (AWT) & Swings Components
Unit - IV Event handling using Abstract Window Toolkit (AWT) & Swings Components
4.1 Component, container, window, frame, panel, use of AWT controls: labels, buttons, checkbox, checkbox group, textfield, textarea
4.2 Use of layout managers: flowLayout, borderLayout, gridLayout, gridBagLayout, menubars, menus, file dialog
4.3 Introduction to swing: Swing features, difference between AWT and Swing.
4.4 Swing components: Icons and Labels, TextField, ComboBox, Button, Checkbox, RadioButton
4.5 Advanced Swing Components: Tabbed Panes, Scroll Panes, Trees, Tables, Progress bar, tool tips
4.6 Introduction to Event Handling: The delegation Event Model: Event sources, Event listeners
4.7 Event classes: The action event class, the Item event class, the Key event class, the mouse event class, text event 4.8 Event listener interfaces: ActionListener , ItemListener , KeyListener , MouseListener , MouseMotion , TextListener
4.1 AWT Packages
AWT is huge! It consists of 12 packages of 370 classes (Swing is even bigger, with 18 packages of 737 classes as of JDK 8). Fortunately, only 2 packages - java.awt and java.awt.event - are commonly-used.
- The java.awt package contains the core AWT graphics classes:
· GUI Component classes, such as Button, TextField, and Label.
· GUI Container classes, such as Frame and Panel.
· Layout managers, such as FlowLayout, BorderLayout and GridLayout.
· Custom graphics classes, such as Graphics, Color and Font.
- The java.awt.event package supports event handling:
· Event classes, such as ActionEvent, MouseEvent, KeyEvent and WindowEvent,
· Event Listener Interfaces, such as ActionListener, MouseListener, MouseMotionListener, KeyListener and WindowListener,
· Event Listener Adapter classes, such as MouseAdapter, KeyAdapter, and WindowAdapter.
AWT provides a platform-independent and device-independent interface to develop graphic programs that runs on all platforms, including Windows, macOS, and Unixes.
4.2 AWT Containers and Components
There are two groups of GUI elements:
- Component (Widget, Control): Components are elementary GUI entities, such as Button, Label, and TextField. They are also called widgets, controls in other graphics systems.
- Container: Containers, such as Frame and Panel, are used to hold components in a specific layout (such as FlowLayout or GridLayout). A container can also hold sub-containers.
In the above figure, there are three containers: a Frame and two Panels. A Frame is the top-level container of an AWT program. A Frame has a title bar (containing an icon, a title, and the minimize/maximize/close buttons), an optional menu bar and the content display area. A Panel is a rectangular area used to group related GUI components in a certain layout. In the above figure, the top-level Frame contains two Panels. There are five components: a Label (providing description), a TextField (for users to enter text), and three Buttons (for user to trigger certain programmed actions).
In a GUI program, a component must be kept (or added) in a container. You need to identify a container to hold the components. Every container has a method called add(Component c). A container (say aContainer) can invoke aContainer.add(aComponent) to add aComponent into itself. For example,
Panel pnl = new Panel(); // Panel is a container
Button btn = new Button("Press"); // Button is a component
pnl.add(btn); // The Panel container adds a Button component.
4.3 AWT Container Classes
Top-Level Containers: Frame, Dialog and Applet
Each GUI program has a top-level container. The commonly-used top-level containers in AWT are Frame, Dialog and Applet:
- A Frame provides the "main window" for your GUI application. It has a title bar (containing an icon, a title, the minimize, maximize/restore-down and close buttons), an optional menu bar, and the content display area. To write a GUI program, we typically start with a subclass
- extending from java.awt.Frame to inherit the main window as follows:
· import java.awt.Frame;// Using Frame class in package java.awt
· // A GUI program is written as a subclass of Frame - the top-level container
· // This subclass inherits all properties from Frame, e.g., title, icon, buttons, content-pane
· public class MyGUIProgramextends Frame {
· // Constructor to setup the GUI components and event handlers
· public MyGUIProgram() { ...... }
· public static void main(String[] args) {
· // Invoke the constructor (to setup the GUI) by allocating an instance
· new MyGUIProgram();
· }
- An AWT Dialog is a "pop-up window" used for interacting with the users. A Dialog has a title-bar (containing an icon, a title and a close button) and a content display area, as illustrated.
- An AWT Applet (in package java.applet) is the top-level container for an applet, which is a Java program running inside a browser. Applet is no longer supported in most of the browsers.
Secondary
Containers: Panel and ScrollPane
Secondary containers are placed inside a top-level container or another secondary container. AWT provides these secondary containers:
- Panel: a rectangular box used to layout a set of related GUI components in pattern such as grid or flow.
- ScrollPane: provides automatic horizontal and/or vertical scrolling for a single child component.
- others.
Hierarchy of the
AWT Container Classes
The hierarchy of the AWT Container classes is as follows:
As illustrated, a Container has a LayoutManager to layout the components in a certain pattern, e.g., flow, grid.
4.4 AWT Component Classes
AWT provides many ready-made and reusable GUI components in package java.awt. The frequently-used are: Button, TextField, Label, Checkbox, CheckboxGroup (radio buttons), List, and Choice, as illustrated below.
AWT GUI
Component: java.awt.Label
A java.awt.Label provides a descriptive text string. Take note that System.out.println() prints to the system console, NOT to the graphics screen. You could use a Label to label another component (such as text field) to provide a text description.
Check the JDK API specification for java.awt.Label.
Constructors
public Label(String strLabel, int alignment); // Construct a Label with the given text String, of the text alignment
public Label(String strLabel); // Construct a Label with the given text String
public Label(); // Construct an initially empty Label
The Label class has three constructors:
- The first constructor constructs a Label object with the given text string in the given alignment. Note that three static constants Label.LEFT, Label.RIGHT, and Label.CENTER are defined in the class for you to specify the alignment (rather than asking you to memorize arbitrary integer values).
- The second constructor constructs a Label object with the given text string in default of left-aligned.
- The third constructor constructs a Label object with an initially empty string. You could set the label text via the setText() method later.
Constants (final static fields)
public static final LEFT; // Label.LEFT
public static final RIGHT; // Label.RIGHT
public static final CENTER; // Label.CENTER
These three constants are defined for specifying the alignment of the Label's text, as used in the above constructor.
Public Methods
// Examples
public String getText();
public void setText(String strLabel);
public int getAlignment();
public void setAlignment(int alignment); // Label.LEFT, Label.RIGHT, Label.CENTER
The getText() and setText() methods can be used to read and modify the Label's text. Similarly, the getAlignment() and setAlignment() methods can be used to retrieve and modify the alignment of the text.
Constructing a Component and Adding
the Component into a Container
Three steps are necessary to create and place a GUI component:
- Declare the component with an identifier (name);
- Construct the component by invoking an appropriate constructor via the new operator;
- Identify the container (such as Frame or Panel) designed to hold this component. The container can then add this component onto itself via aContainer.add(aComponent) method. Every container has a add(Component) method. Take note that it is the container that actively and explicitly adds a component onto itself, NOT the other way.
Example
Label lblInput; // Declare an Label instance called lblInput
lblInput = new Label("Enter ID"); // Construct by invoking a constructor via the new operator
add(lblInput); // this.add(lblInput) - "this" is typically a subclass of Frame
lblInput.setText("Enter password"); // Modify the Label's text string
lblInput.getText(); // Retrieve the Label's text string
AWT GUI
Component: java.awt.Button
A java.awt.Button is a GUI component that triggers a certain programmed action upon clicking.
Constructors
public Button(String btnLabel);
// Construct a Button with the given label
public Button();
// Construct a Button with empty label
The Button class has two constructors. The first constructor creates a Button object with the given label painted over the button. The second constructor creates a Button object with no label.
Public Methods
public String getLabel();
// Get the label of this Button instance
public void setLabel(String btnLabel);
// Set the label of this Button instance
public void setEnable(booleanenable);
// Enable or disable this Button. Disabled Button cannot be clicked.
The getLabel() and setLabel() methods can be used to read the current label and modify the label of a button, respectively.
Note: The latest Swing's JButton replaces getLabel()/setLabel() with getText()/setText() to be consistent with all the components. We will describe Swing later.
Event
Clicking a button fires a so-called ActionEvent and triggers a certain programmed action. I will explain event-handling later.
Example
Button btnColor = new Button("Red"); // Declare and allocate a Button instance called btnColor
add(btnColor); // "this" Container adds the Button
...
btnColor.setLabel("Green"); // Change the button's label
btnColor.getLabel(); // Read the button's label
AWT GUI
Component: java.awt.TextField
A java.awt.TextField is single-line text box for users to enter texts. (There is a multiple-line text box called TextArea.) Hitting the "ENTER" key on a TextField object fires an ActionEvent.
Constructors
public TextField(String initialText, int columns);
// Construct a TextField instance with the given initial text string with the number of columns.
public TextField(String initialText);
// Construct a TextField instance with the given initial text string.
public TextField(int columns);
// Construct a TextField instance with the number of columns.
Public Methods
public String getText();
// Get the current text on this TextField instance
public void setText(String strText);
// Set the display text on this TextField instance
public void setEditable(booleaneditable);
// Set this TextField to editable (read/write) or non-editable (read-only)
Event
Hitting the "ENTER" key on a TextField fires a ActionEvent, and triggers a certain programmed action.
Example
TextFieldtfInput = new TextField(30); // Declare and allocate an TextField instance called tfInput
add(tfInput); // "this" Container adds the TextField
TextFieldtfResult = new TextField(); // Declare and allocate an TextField instance called tfResult
tfResult.setEditable(false) ; // Set to read-only
add(tfResult); // "this" Container adds the TextField
......
// Read an int from TextField "tfInput", square it, and display on "tfResult".
// getText() returns a String, need to convert to int
int number = Integer.parseInt(tfInput.getText());
number *= number;
// setText() requires a String, need to convert the int number to String.
tfResult.setText(number + "");
Take note that getText()/SetText() operates on String. You can convert a String to a primitive, such as int or double via static method Integer.parseInt() or Double.parseDouble(). To convert a primitive to a String, simply concatenate the primitive with an empty String.
4.5 Example
1: AWTCounter
Let's assemble a few components together into a simple GUI counter program, as illustrated. It has a top-level container Frame, which contains three components - a Label "Counter", a non-editable TextField to display the current count, and a "Count" Button. The TextField shall display count of 0 initially.
Each time you click the button, the counter's value increases by 1.
AWT Event-Handling
Java adopts the so-called
"Event-Driven" (or "Event-Delegation") programming model
for event-handling, similar to most of the visual programming languages like
Visual Basic.
In event-driven programming, a piece of
event-handling codes is executed (or called
back by the graphics subsystem) when an event was fired in response to
an user input (such as clicking a mouse button or hitting the ENTER key in a
text field).
Callback Methods
In the above examples, the
method actionPerformed() is known as a callback method. In other words, you never
invoke actionPerformed() in your codes explicitly.
The actionPerformed() is called
back by the graphics subsystem under certain circumstances in response
to certain user actions.
JavaScript can attach a Callback
method to an Event Directly
In some languages, you can directly attach
a method (or function) to an event (such as mouse-click). For example, the
following JavaScript code (called JSCounter.html) implement a counter
similar to the AWTCounter, with a text label, text field and button:
In Java, we CANNOT attach a method to a
source object directly, as method is not a first-class object in Java. For
example, a Java method cannot accept methods as its arguments and it cannot
return a method; you cannot assign a method to a variable, etc. (JavaScript and
C language CAN!).
Source, Event and Listener Objects
The AWT's event-handling classes are kept
in package java.awt.event.
Three kinds of objects are involved in the
event-handling: a source, listener(s) and an event object.
The source object (such as Button and Textfield)
interacts with the user. Upon triggered, the source object creates an event object to capture the action
(e.g., mouse-click x and y, texts entered, etc). This event object will be messaged to all the registered listener object(s), and
an appropriate event-handler method of the listener(s) is called-back to
provide the response. In other words, triggering
a source fires an event to all its listener(s), and invoke an appropriate event handler of the listener(s).
To express interest for a certain source's
event, the listener(s) must be registered with the source. In other words, the
listener(s) "subscribes" to a source's event, and the source
"publishes" the event to all its subscribers upon activation. This is
known as subscribe-publish or observable-observer design pattern.
The sequence of steps is illustrated above:
- The source object registers its listener(s) for a certain type of event.
A source fires an event when triggered. For
example, clicking a Button fires an ActionEvent, clicking a
mouse button fires MouseEvent, typing a key fires KeyEvent, and etc.
How the source and listener understand each
other? The answer is via an agreed-upon interface. For example, if a source is
capable of firing an event called XxxEvent (e.g., ActionEvent).
Firstly, we need to declare an interface
called XxxListener (e.g., ActionListener) containing the names
of the handler methods (recall that an interface contains
only abstract methods without implementation). For example,
the ActionListener interface is declared as follows:
// An ActionListener interface, which
declares the signature of the handlers
public interface
ActionListener {
public void actionPerformed(ActionEvent
evt);
}
Secondly, all XxxEvent listeners
must implement the XxxListener interface. That is, the listeners must
provide their own implementations (i.e., programmed responses) to all
the abstract methods declared in the XxxListener interface.
In this way, the listener(s) can response to these events appropriately. For
example,
// An example of MouseListener, which provides implementation to the event
handler methods
class MyActionListener implement ActionListener {
@Override
public void actionPerformed(ActionEvent
evt) {
System.out.println("ActionEvent detected!");
}
}
Thirdly, in the source, we need to maintain
a list of XxxEvent listener object(s), and define two
methods: addXxxListener() and removeXxxListener() to add
and remove a XxxEvent listener from this list. For
the ActionEvent, the signature of the methods are:
public void
addActionListener(ActionListener lis);
public void
removeActionListener(ActionListener lis);
Take note that
the addXxxListener() takes a XxxListener object as its sole
parameter. In other words, it can only add objects of the
type XxxListener, and its sub-type. Since XxxListener is
an interface, you cannot create instance of XxxListener, but need to
create instance of a subclass implementing the XxxListener interface.
In summary, we identify the source, the
event-listener interface, and the listener object. The listener must implement
the event-listener interface. The source object then registers listener object
via the addXxxListener(XxxListener lis) method.
- The source
is triggered by a user.
- The
source create a XxxEvent object, which encapsulates the
necessary information about the activation. For example, the (x,
y) position of the mouse pointer, the text entered, etc.
- Finally,
for each of the XxxEvent listeners in the listener list, the
source invokes the appropriate handler on the listener(s), which provides
the programmed response.
1 AWTCounter: ActionEvent and ActionListener Interface
Clicking a Button (or hitting the
"Enter" key on a TextField) fires an ActionEvent to
all its ActionEvent listener(s). An ActionEvent listener
must implement the ActionListener interface, which declares
one abstract method called actionPerformed() as follow:
public interface ActionListener {
public void actionPerformed(ActionEvent
evt);
// Called back upon button-click (on Button), enter-key pressed (on
TextField)
}
Here are the event-handling steps:
●
We
identify btnCount (of Button) as the source object.
●
Clicking Button fires
an ActionEvent to all its ActionEvent listener(s).
●
The listener(s) is required to
implement ActionListener interface, and override
the actionPerformed() method to provide the response. In Line 56-65,
we write an inner class called BtnCountListener, which override
the actionPerformed() to increment and display the count. An inner class is a class defined
inside an outer class, and it can access the private entities of the outer
class. We will elaborate on the inner class in the next section.
●
The source object registers
listener via the addActionListener(). In this example, the source btnCount (Button) adds
an instance of BtnCountListener as a listener via:
●
BtnCountListener listener = new
BtnCountListener();
btnCount.addActionListener(listener);
Note
that addActionListener() takes an argument of the type ActionListener. BtnCountListener,
which implements ActionListener interface (i.e., a subclass
of ActionListener), is upcasted and passed to
the addActionListener() method.
●
Upon button-click,
the btnCount creates an ActionEvent object, and calls back
the actionPerformed(ActionEvent) method of all its registered
listener(s) with the ActionEvent object created:
●
ActionEvent evt = new
ActionEvent( ...... );
listener.actionPerformed(evt); //
for all its listener(s)
The sequence diagram is as follows:
3.2 Revisit Example
2 AWTAccumulator: ActionEvent and ActionListener Interface
In this example,
- We
identify the tfInput (of TextField) as the source object.
- Hitting
the "Enter" key on a TextField fires
an ActionEvent to all its ActionEvent listener(s).
- In Line
46-59, we define an inner class called TFInputListener as
the ActionEvent listener.The ActionEvent listener is
required to implement the ActionListener interface, and override
the actionPerformed() method to provide the programmed response
upon activation.
- The
source object tfInput (of TextField) registers an anonymous
instance of TFInputListener as
its ActionEvent listener via
the tfInput.addActionListener(new TFInputListener()) (Line 23).
4.3 Example
3: WindowEvent and WindowListener Interface
A WindowEvent is fired (to all
its WindowEvent listeners) when a window (e.g., Frame) has been
opened/closed, activated/deactivated, iconified/deiconified via the 3 buttons
at the top-right corner or other means. The source of WindowEvent shall
be a top-level window-container such as Frame.
A WindowEvent listener must
implement WindowListener interface, which declares
7 abstract event-handling methods, as follows. Among them,
the windowClosing(), which is called back upon clicking the window-close
button, is the most commonly-used.
public void windowClosing(WindowEvent evt)
//
Called-back when the user attempts to close the window by clicking the window
close button.
//
This is the most-frequently used handler.
public void windowOpened(WindowEvent evt)
// Called-back the first time a window is
made visible.
public void windowClosed(WindowEvent evt)
//
Called-back when a window has been closed as the result of calling dispose on
the window.
public void windowActivated(WindowEvent
evt)
//
Called-back when the Window is set to be the active Window.
public void windowDeactivated(WindowEvent
evt)
//
Called-back when a Window is no longer the active Window.
public void windowIconified(WindowEvent
evt)
//
Called-back when a window is changed from a normal to a minimized state.
public void windowDeiconified(WindowEvent
evt)
//
Called-back when a window is changed from a minimized to a normal state.
The following program added support for
"close-window button" to "Example 1: AWTCounter".
|
|
|
In this example, we shall modify the
earlier AWTCounter example to handle the WindowEvent. Recall
that pushing the "close-window" button on
the AWTCounter has no effect, as it did not handle
the WindowEvent of windowClosing(). We included
the WindowEvent handling codes in this example.
- We
identify the super Frame as the source object.
- The Frame fires
the WindowEvent to all its
registered WindowEvent listener(s).
- In Line
53-69, we define an inner class called MyWindowListener as
the WindowEvent listener. It is required to implement
the WindowListener interface, which declares 7 abstract
methods: windowOpened(), windowClosed(), windowClosing(), windowActivated(), windowDeactivated(), windowIconified() and windowDeiconified().
- We
register an anonymous instance of MyWindowListener as
the WindowEvent listener to the source Frame via
method addWindowListener(new MyWindowListener()).
- We
override the windowClosing() handler to terminate the program
using System.exit(0). We ignore the other 6 handlers, but required to
provide an empty body for compilation.
The sequence diagram is as follow:
4.4 Example
4: MouseEvent and MouseListener Interface
A MouseEvent is fired when you
press, release, or click (press followed by release) a mouse-button (left or
right button) at the source object; or position the mouse-pointer at (enter)
and away (exit) from the source object.
A MouseEvent listener must
implement the MouseListener interface, which declares the following
five abstract methods:
public void mouseClicked(MouseEvent evt)
//
Called-back when the mouse-button has been clicked (pressed followed by
released) on the source.
public void mousePressed(MouseEvent evt)
public void mouseReleased(MouseEvent evt)
//
Called-back when a mouse-button has been pressed/released on the source.
//
A mouse-click invokes mousePressed(), mouseReleased() and mouseClicked().
public void mouseEntered(MouseEvent evt)
public void mouseExited(MouseEvent evt)
//
Called-back when the mouse-pointer has entered/exited the source.
.
To demonstrate the MouseEvent:
- We
identity super Frame as the source object.
- The Frame fires
a MouseEvent to all its MouseEvent listener(s) when
you click/press/release a mouse-button or enter/exit with the
mouse-pointer.
- In Line
42-56, we define an inner class called MyMouseListener as
the MouseEvent listener. It is required to implement
the MouseListener interface, which declares 5 abstract
methods: mouseClicked(), mousePressed(), mouseReleased(), mouseEntered(),
and mouseExit(). We override the mouseClicked() to display
the (x, y) coordinates of the mouse click on the two
displayed TextFields. We ignore all the other handlers (for
simplicity - but you need to provide an empty body for compilation).
- We
register an anonymous instance of MyMouseListener as
the MouseEvent listener to super Frame (source)
via the method addMouseListener(new MyMouseListener()).
Try: Include a WindowListener to handle the close-window
button.
3.5 Example
5: MouseEvent and MouseMotionListener Interface
A MouseEvent is also fired when
you move and drag the mouse pointer at the source object. But you need to
use MouseMotionListener to handle the mouse-move and mouse-drag.
The MouseMotionListener interface declares the following two abstract
methods:
public void mouseDragged(MouseEvent e)
//
Called-back when a mouse-button is pressed on the source component and then
dragged.
public void mouseMoved(MouseEvent e)
//
Called-back when the mouse-pointer has been moved onto the source component but
no buttons have been pushed.
In this example, we shall illustrate both
the MouseListener and MouseMotionListener.
- We
identify the super Frame as the source, which fires
the MouseEvent to its registered MouseListener and MouseMotionListener.
- In Line
53-80, we define an inner class called MyMouseListener as both
the MouseListener and MouseMotionListener.
- We
register an instance of MyMouseListener as the listener
to super Frame via
method addMouseListener() and addMouseMotionListener().
- The MouseMotionListener needs
to implement 2 abstract
methods: mouseMoved() and mouseDragged() declared in
the MouseMotionListener interface.
- We
override the mouseMoved() to display the (x, y) position of the
mouse pointer. We ignore the MouseDragged() handler by providing
an empty body for compilation.
Try: Include a WindowListener to handle the close-window
button.
3.6 Example
6: KeyEvent and KeyListener Interface
A KeyEvent is fired when you
pressed, released, and typed (pressed followed by released) a key on the source
object. A KeyEvent listener must
implement KeyListener interface, which declares three abstract
methods:
public void keyTyped(KeyEvent e)
//
Called-back when a key has been typed (pressed and released).
public void keyPressed(KeyEvent e)
public void keyReleased(KeyEvent e)
//
Called-back when a key has been pressed or released.
|
import java.awt.*; import java.awt.event.*;
// An AWT GUI program inherits from the
top-level container java.awt.Frame public class KeyEventDemo extends Frame {
private TextField tfInput; //
Single-line TextField to receive tfInput key
private TextArea taDisplay; // Multi-line TextArea to taDisplay result
// Constructor to setup the GUI components and event handlers
public KeyEventDemo() {
setLayout(new FlowLayout()); // "super" frame sets to
FlowLayout
add(new Label("Enter Text: "));
tfInput = new TextField(10);
add(tfInput);
taDisplay = new TextArea(5, 40); // 5 rows, 40 columns
add(taDisplay);
tfInput.addKeyListener(new MyKeyListener());
// tfInput TextField (source) fires KeyEvent.
// tfInput adds an anonymous instance of MyKeyListener
// as a KeyEvent listener.
setTitle("KeyEvent Demo"); // "super" Frame sets
title
setSize(400, 200); //
"super" Frame sets initial size
setVisible(true); //
"super" Frame shows
}
// The entry main() method
public static void main(String[] args) {
new KeyEventDemo(); // Let the
constructor do the job
}
// Define an inner class to handle KeyEvent
private class MyKeyListener implements KeyListener {
// Called back when a key has been typed (pressed and released)
@Override
public void keyTyped(KeyEvent evt) {
taDisplay.append("You have typed " + evt.getKeyChar() +
"\n");
}
// Not Used, but need to provide an empty body for compilation
@Override public void keyPressed(KeyEvent evt) { }
@Override public void keyReleased(KeyEvent evt) { }
} } |
In this example:
- We
identify the tfInput (of TextField) as the source object.
- The
source fires a KeyEvent when you press/release/type a key to all
its KeyEvent listener(s).
- In Line
35-46, we define an inner class called MyKeyListener as
the KeyEvent listener.
- We
register an anonymous instance of MyKeyListener as
the KeyEvent listener to the source TextField via
method input.addKeyListener().
- The KeyEvent listener
needs to implement the KeyListener interface, which declares 3
abstract methods: keyTyped(), keyPressed(), keyReleased().
- We
override the keyTyped() to display key typed on the
display TextArea. We ignore
the keyPressed() and keyReleased().
Layout
Managers and Panel
A container has a so-called layout manager to arrange its
components. The layout managers provide a level of abstraction to map your user
interface on all windowing systems, so that the layout can be platform-independent.
AWT provides the following layout managers
(in
package java.awt): FlowLayout, GridLayout, BorderLayout, GridBagLayout, BoxLayout, CardLayout,
and others. Swing added more layout manager in package javax.swing, to be
described later.
Container's setLayout() method
A container has
a setLayout() method to set its layout manager:
// java.awt.Container
public void setLayout(LayoutManager mgr)
To set up the layout of
a Container (such as Frame, JFrame, Panel,
or JPanel), you have to:
- Construct
an instance of the chosen layout object, via new and
constructor, e.g., new FlowLayout())
- Invoke
the setLayout() method of the Container, with the layout
object created as the argument;
- Place
the GUI components into the Container using
the add() method in the correct order; or into the correct
zones.
For example,
// Allocate a Panel (container)
Panel pnl = new Panel();
// Allocate a new Layout object. The Panel
container sets to this layout.
pnl.setLayout(new FlowLayout());
// The Panel container adds components in
the proper order.
pnl.add(new JLabel("One"));
pnl.add(new JLabel("Two"));
pnl.add(new JLabel("Three"));
......
Container's getLayout() method
You can get the current layout
via Container's getLayout() method.
Panel pnl = new Panel();
System.out.println(pnl.getLayout());
// java.awt.FlowLayout[hgap=5,vgap=5,align=center]
Panel's
Initial Layout
Panel (and Swing's JPanel)
provides a constructor to set its initial layout manager. It is because a
primary function of Panel is to layout a group of component in a
particular layout.
public void Panel(LayoutManager layout)
//
Construct a Panel in the given layout
//
By default, Panel (and JPanel) has FlowLayout
// For example, create a Panel in
BorderLayout
Panel pnl = new Panel(new BorderLayout());
FlowLayout
In the java.awt.FlowLayout, components
are arranged from left-to-right inside the container in the order that they are
added (via method aContainer.add(aComponent)). When one row is filled, a
new row will be started. The actual appearance depends on the width of the
display window.
Constructors
public FlowLayout();
public FlowLayout(int
alignment);
public FlowLayout(int
alignment, int hgap, int vgap);
// alignment: FlowLayout.LEFT (or LEADING),
FlowLayout.RIGHT (or TRAILING), or FlowLayout.CENTERs
// hgap, vgap: horizontal/vertical gap between the components
//
By default: hgap = 5, vgap = 5, alignment = FlowLayout.CENTER
Example
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import java.awt.*; import java.awt.event.*; // An AWT GUI program inherits the
top-level container java.awt.Frame public class AWTFlowLayoutDemo extends Frame {
private Button btn1, btn2, btn3, btn4, btn5, btn6;
// Constructor to setup GUI components and event handlers
public AWTFlowLayoutDemo () {
setLayout(new FlowLayout());
// "super" Frame sets layout to FlowLayout, which arranges
the components
// from left-to-right, and flow from top-to-bottom.
btn1 = new Button("Button 1");
add(btn1);
btn2 = new Button("This is Button 2");
add(btn2);
btn3 = new Button("3");
add(btn3);
btn4 = new Button("Another Button 4");
add(btn4);
btn5 = new Button("Button 5");
add(btn5);
btn6 = new Button("One More Button 6");
add(btn6);
setTitle("FlowLayout Demo"); // "super" Frame sets
title
setSize(280, 150); //
"super" Frame sets initial size
setVisible(true); //
"super" Frame shows
}
// The entry main() method
public static void main(String[] args) {
new AWTFlowLayoutDemo(); // Let
the constructor do the job
} } |
7.2 GridLayout
In java.awt.GridLayout, components are
arranged in a grid (matrix) of rows and columns inside the Container.
Components are added in a left-to-right, top-to-bottom manner in the order they
are added (via method aContainer.add(aComponent)).
Constructors
public GridLayout(int
rows, int columns);
public GridLayout(int
rows, int columns, int hgap, int vgap);
// By default: rows = 1, cols = 0, hgap = 0, vgap = 0
Example
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import java.awt.*; import java.awt.event.*; // An AWT GUI program inherits the
top-level container java.awt.Frame public class AWTGridLayoutDemo extends Frame {
private Button btn1, btn2, btn3, btn4, btn5, btn6;
// Constructor to setup GUI components and event handlers
public AWTGridLayoutDemo () {
setLayout(new GridLayout(3, 2, 3, 3));
// "super" Frame sets layout to 3x2 GridLayout, horizontal
and vertical gaps of 3 pixels
// The components are added from left-to-right, top-to-bottom
btn1 = new Button("Button 1");
add(btn1);
btn2 = new Button("This is Button 2");
add(btn2);
btn3 = new Button("3");
add(btn3);
btn4 = new Button("Another Button 4");
add(btn4);
btn5 = new Button("Button 5");
add(btn5);
btn6 = new Button("One More Button 6");
add(btn6);
setTitle("GridLayout Demo"); // "super" Frame sets
title
setSize(280, 150); //
"super" Frame sets initial size
setVisible(true); //
"super" Frame shows
}
// The entry main() method
public static void main(String[] args) {
new AWTGridLayoutDemo(); // Let
the constructor do the job
} } |
7.3 BorderLayout
In java.awt.BorderLayout, the
container is divided into 5
zones: EAST, WEST, SOUTH, NORTH, and CENTER.
Components are added using method aContainer.add(aComponent, zone), where zone is
either BorderLayout.NORTH (or PAGE_START), BorderLayout.SOUTH (or PAGE_END), BorderLayout.WEST (or LINE_START), BorderLayout.EAST (or LINE_END),
or BorderLayout.CENTER.
You need not place components to all the 5
zones. The NORTH and SOUTH components may be stretched
horizontally; the EAST and WEST components may be stretched
vertically; the CENTER component may stretch both horizontally and
vertically to fill any space left over.
Constructors
public BorderLayout();
public BorderLayout(int
hgap, int vgap);
// By default hgap = 0, vgap = 0
Example
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import java.awt.*; import java.awt.event.*; // An AWT GUI program inherits the
top-level container java.awt.Frame public class AWTBorderLayoutDemo extends Frame {
private Button btnNorth, btnSouth, btnCenter, btnEast, btnWest;
// Constructor to setup GUI components and event handlers
public AWTBorderLayoutDemo () {
setLayout(new BorderLayout(3, 3));
// "super" Frame sets layout to BorderLayout,
// horizontal and vertical gaps of 3 pixels
// The components are added to the specified zone
btnNorth = new Button("NORTH");
add(btnNorth, BorderLayout.NORTH);
btnSouth = new Button("SOUTH");
add(btnSouth, BorderLayout.SOUTH);
btnCenter = new Button("CENTER");
add(btnCenter, BorderLayout.CENTER);
btnEast = new Button("EAST");
add(btnEast, BorderLayout.EAST);
btnWest = new Button("WEST");
add(btnWest, BorderLayout.WEST);
setTitle("BorderLayout Demo"); // "super" Frame
sets title
setSize(280, 150);
// "super" Frame sets initial size
setVisible(true);
// "super" Frame shows
}
// The entry main() method
public static void main(String[] args) {
new AWTBorderLayoutDemo(); //
Let the constructor do the job
} } |
7.4 Using Panels
as Sub-Container to Organize Components
An AWT Panel is a rectangular
pane, which can be used as sub-container to organized a group of related
components in a specific layout
(e.g., FlowLayout, BorderLayout). Panels are secondary containers, which shall
be added into a top-level container (such as Frame), or
another Panel.
For example, the following figure shows
a Frame in BorderLayout containing
two Panels - panelResult in FlowLayout and panelButtons in GridLayout. panelResult is
added to the NORTH, and panelButtons is added to
the CENTER.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
import java.awt.*; import java.awt.event.*; // An AWT GUI program inherits the
top-level container java.awt.Frame public class AWTPanelDemo extends Frame {
private Button[] btnNumbers; //
Array of 10 numeric Buttons
private Button btnHash, btnStar;
private TextField tfDisplay;
// Constructor to setup GUI components and event handlers
public AWTPanelDemo () {
// Set up display panel
Panel panelDisplay = new Panel(new FlowLayout());
tfDisplay = new TextField("0", 20);
panelDisplay.add(tfDisplay);
// Set up button panel
Panel panelButtons = new Panel(new GridLayout(4, 3));
btnNumbers = new Button[10]; //
Construct an array of 10 numeric Buttons
btnNumbers[1] = new Button("1"); // Construct Button "1"
panelButtons.add(btnNumbers[1]);
// The Panel adds this Button
btnNumbers[2] = new Button("2");
panelButtons.add(btnNumbers[2]);
btnNumbers[3] = new Button("3");
panelButtons.add(btnNumbers[3]);
btnNumbers[4] = new Button("4");
panelButtons.add(btnNumbers[4]);
btnNumbers[5] = new Button("5");
panelButtons.add(btnNumbers[5]);
btnNumbers[6] = new Button("6");
panelButtons.add(btnNumbers[6]);
btnNumbers[7] = new Button("7");
panelButtons.add(btnNumbers[7]);
btnNumbers[8] = new Button("8");
panelButtons.add(btnNumbers[8]);
btnNumbers[9] = new Button("9");
panelButtons.add(btnNumbers[9]); // You should use a loop for the
above statements!!!
btnStar = new Button("*");
panelButtons.add(btnStar);
btnNumbers[0] = new Button("0");
panelButtons.add(btnNumbers[0]);
btnHash = new Button("#");
panelButtons.add(btnHash);
setLayout(new BorderLayout());
// "super" Frame sets to BorderLayout
add(panelDisplay, BorderLayout.NORTH);
add(panelButtons, BorderLayout.CENTER);
setTitle("BorderLayout Demo"); // "super" Frame
sets title
setSize(200, 200);
// "super" Frame sets initial size
setVisible(true);
// "super" Frame shows
}
// The entry main() method
public static void main(String[] args) {
new AWTPanelDemo(); // Let the
constructor do the job
} } |
7.5 GridBagLayout
Reference: Read "How to Use GridBagLayout" @
https://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html.
7.6 Example
1
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
import java.awt.*; import javax.swing.*;
@SuppressWarnings("serial") public class GridBagLayoutExample extends
JPanel {
JButton button1, button2, button3, button4, button5;
// Constructor
public GridBagLayoutExample() {
super.setLayout(new GridBagLayout());
// super JPanel
GridBagConstraints gbc = new GridBagConstraints();
// The following constraints are applicable to all components //
gbc.fill = GridBagConstraints.HORIZONTAL;
// Define constraints for individual components
button1 = new JButton("B1");
gbc.gridx = 0; // column 0
(first column)
gbc.gridy = 0; // row 0 (first
row) //
gbc.weightx = 0.5; // weight
for distributing extra x-spaces
super.add(button1, gbc); // add
and apply constraints
button2 = new JButton("B2");
gbc.gridx = 1; // column 1
gbc.gridy = 0; // row 0 //
gbc.weightx = 1.0;
super.add(button2, gbc);
button3 = new JButton("B3");
gbc.gridx = 2; // column 2
gbc.gridy = 0; // row 0 //
gbc.weightx = 0.5;
super.add(button3, gbc);
button4 = new JButton("Long-Named Button 4");
gbc.gridx = 0; // column 0
gbc.gridy = 1; // row 1 (second
row)
gbc.gridwidth = 3; // span 3
columns
gbc.ipady = 40; // internal
padding-y
super.add(button4, gbc);
button5 = new JButton("5");
gbc.gridx = 1; // second
column
gbc.gridy = 2; // third row
gbc.gridwidth = 2; // span 2
columns
gbc.ipady = 0; // reset to
default
gbc.anchor = GridBagConstraints.PAGE_END; // align at bottom of space
gbc.insets = new Insets(10, 0, 0, 0); // top margin //
gbc.weighty = 1.0; // request
any extra vertical space
super.add(button5, gbc);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() { JFrame frame = new
JFrame("GridBagLayoutDemo"); frame.setContentPane(new
GridBagLayoutExample());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300,300); frame.setVisible(true);
}
});
} } |
Run the program, the output is in (a),
where all components have their natural width and height, placed in center
(anchor=CENTER) with extra x and y spaces at the 4 margins.
The ipady increases the internal y-padding for button-4 (spans 3
columns). Button 5 (spans second and third columns) has top margin specified
by insets, and anchor at the bottom-right corner (anchor=PAGE_END).
Uncomment the gbc.fill =
GridBagConstraints.HORIZONTAL (line 14). The output is in (b), where ALL
components fill horizontally with equal column width.
Uncomment all weightx (lines 20,
26, 32). The output is in (c). The extra x spaces are distributed according to
the weightx of (0.5, 1.0, 0.5).
Uncomment the weighty (line 49).
The output is in (d). The extra y spaces are given to row 3, as row 1 and 2
have weighty of 0 and non-participating in the distribution of extra
y-spaces.
7.7 BoxLayout
BoxLayout arrange components in a single
row or column. It respects components' requests on the minimum sizes.
[TODO] Example and diagram
8. Swing
8.1 Introduction
Swing is part of the so-called "Java
Foundation Classes (JFC)" (have you heard of MFC?), which was introduced
in 1997 after the release of JDK 1.1. JFC was subsequently included as an
integral part of JDK since JDK 1.2. JFC consists of:
●
Swing API: for advanced
graphical programming.
●
Accessibility API: provides
assistive technology for the disabled.
●
Java 2D API: for high quality
2D graphics and images.
●
Pluggable look and feel
supports.
●
Drag-and-drop support between
Java and native applications.
The goal of Java GUI programming is to
allow the programmer to build GUI that looks good on ALL platforms. JDK 1.0's
AWT was awkward and non-object-oriented (using many event.getSource()).
JDK 1.1's AWT introduced event-delegation (event-driven) model, much clearer
and object-oriented. JDK 1.1 also introduced inner class and JavaBeans – a
component programming model for visual programming environment (similar to
Visual Basic).
Swing appeared after JDK 1.1. It was introduced
into JDK 1.1 as part of an add-on JFC (Java Foundation Classes). Swing is a
rich set of easy-to-use, easy-to-understand JavaBean GUI components that can be
dragged and dropped as "GUI builders" in visual programming
environment. Swing is now an integral part of Java since JDK 1.2.
Swing's Features
Swing is huge (consists of 18 packages of
737 classes as in JDK 1.8) and has great depth. Compared with AWT, Swing
provides a huge and comprehensive collection of reusable GUI components, as
shown in the Figure below (extracted form Swing Tutorial).
The main features of Swing are (extracted
from the Swing website):
- Swing is
written in pure Java (except a few classes) and therefore is 100%
portable.
- Swing
components are lightweight.
The AWT components are heavyweight (in
terms of system resource utilization). Each AWT component has its own
opaque native display, and always displays on top of the lightweight
components. AWT components rely heavily on the underlying windowing
subsystem of the native operating system. For example, an AWT button ties
to an actual button in the underlying native windowing subsystem, and
relies on the native windowing subsystem for their rendering and
processing. Swing components (JComponents) are written in Java. They are
generally not "weight-down" by complex GUI considerations
imposed by the underlying windowing subsystem.
- Swing
components support pluggable
look-and-feel. You can choose between Java look-and-feel and the look-and-feel of the underlying OS (e.g., Windows, UNIX
or macOS). If the later is chosen, a Swing button runs on the Windows
looks like a Windows' button and feels like a Window's button. Similarly,
a Swing button runs on the UNIX looks like a UNIX's button and feels like
a UNIX's button.
- Swing
supports mouse-less operation,
i.e., it can operate entirely using keyboard.
- Swing
components support "tool-tips".
- Swing
components are JavaBeans –
a Component-based Model used in Visual Programming (like Visual Basic).
You can drag-and-drop a Swing component into a "design form"
using a "GUI builder" and double-click to attach an event
handler.
- Swing
application uses AWT event-handling classes (in
package java.awt.event). Swing added some new classes in
package javax.swing.event, but they are not frequently used.
- Swing
application uses AWT's layout manager (such
as FlowLayout and BorderLayout in
package java.awt). It added new layout managers, such
as Springs, Struts, and BoxLayout (in
package javax.swing).
- Swing
implements double-buffering and
automatic repaint batching for smoother screen repaint.
- Swing
introduces JLayeredPane and JInternalFrame for
creating Multiple Document Interface (MDI) applications.
- Swing
supports floating toolbars (in JToolBar), splitter control,
"undo".
- Others -
check the Swing website.
Using Swing API
If you understood the AWT programming (in
particular, container/component and event-handling), switching over to Swing
(or any other Graphics packages) is straight-forward.
Swing's Components
Compared with the AWT component classes (in
package java.awt), Swing component classes (in package javax.swing)
begin with a prefix "J",
e.g., JButton, JTextField, JLabel, JPanel, JFrame,
or JApplet.
Comments
Post a Comment