Вы находитесь на странице: 1из 42

Graphical User Interfaces

Programming with Java’s Swing API

February 4, 2003
CMPS 109 ! Advanced Programming
Priorities
Does your program do what it is supposed to?
If the program doesn’t work, there’s no point to using it.

Is the program’s use easy to understand for its


intended audience?
If the people you are writing the program for don’t understand how
it works, they can’t use it.

Does the program perform at an acceptable


speed?
If it takes forever to run, people will not want to use it.
Interfaces
Interfaces are everywhere in programming
Application Program Interface !API"
Class interface
Library interface

User Interfaces !UIs" are how your program


interacts with the outside world.

Most UIs are bad.


Programmers don’t have the training to create a good UI.
Psychology is providing the framework for understanding what
makes a good User Interface.
Graphical Interfaces
Graphical User Interfaces !GUIs" provide the
users with an easily understood metaphor for
interacting with a computer.

GUIs consist of “Windows” that are blocked


off areas of the screen, and “Components” or
“Widgets” within those Windows.

Examples of Components:
Labels, Buttons, Images, Text Entry boxes, Lists, Trees, Menus, etc.
AWT and Swing
The Abstract Windowing Toolkit !AWT" was
Java’s original GUI toolkit.
It used “native” widgets.
It was difficult to program.
It did not support a wide range of widgets.

Swing was introduced with Java 2 !the Java 1.2


API"
It only used native windows, all other widgets were drawn “by
hand”.
Swing supports a wider range of widgets, and is easily extended.
Java Swing

Swing has its own


“Look and Feel” that
is distinct from the
“native” look and
feel of the systems it
runs on.
Many companies have
developed their own
Look and Feel so that
users can’t see the
difference.
A Small Sample
import java.awt.*;
import javax.swing.*;

class HelloButton {
public static void main( String[] args )
{
JFrame frame = new JFrame( “Hello Button” );
Container pane = frame.getContentPane();
JButton hello = new JButton( “Hello, world!” );
pane.add( hello );
frame.pack();
frame.show();
}
}
What to import
import java.awt.*;
import javax.swing.*;

...

You need to import both java.awt.* and


javax.swing.* to get all the basic classes.
Creating a JFrame
...

JFrame frame = new JFrame( “Hello Button” );


...

Creating a JFrame gives you a “top level”


container.
“Top level” containers are backed by native UI components !usually
Windows or Dialogs".

The string passed to the constructor is the


title of the window.
The Content Pane
...

Container pane = frame.getContentPane();


...

You can’t add components directly to a


JFrame.
JFrame uses different layers !panes" to support various Swing
features !Drag and Drop, ToolTips, etc".

Instead, you must add to the frame’s Content


Pane.
Call getContentPane!" to get the content pane.
Adding content
...

JButton hello = new JButton( “Hello, world!” );

pane.add( hello );
...
Create another Swing component.
In this case, a standard push%button is created with the label “Hello,
World!”.
This button doesn’t do anything when pushed.

Call add() with the component as a parameter


to add it to the frame’s content pane.
Resizing and showing
...

frame.pack();

frame.show();
...

pack!" will resize the frame to the minimum


size needed to display the items in the
content pane.

Calling show!" will show the JFrame.


You must set the size of the frame !directly or with pack!"" before
you show the frame.
Quitting your program?
When you close the window, you might
notice that your program does not quit.

When the first Swing component is created, a


new Thread is created also.
Threads allow a single program to do two things “at the same time.”
In Swing’s case, the new thread is created to track and capture
events !mouse, keyboard, etc".

We’ll cover how to handle quitting and


threads in Swing a little later.
Swing Components
Swing Provides the following Components:
Buttons: Containers: Lists:
JButton JPanel JList
JCheckBox JFrame JTree
JRadioButton JDialog JTable

Menus: Miscellaneous: Organizers:


JMenuBar JFileChooser JSplitPane
JMenu JCollerChooser JTabbedPane
JMenuItem JToolTip JToolBar

Ranged Controls: Scrolling: Text:


JSpinner JScrollBar JTextArea
JSlider JScrollPane JTextField
JProgressBar JLabel
The Event Thread

Threads are a way of separating the work that


a program does into multiple execution paths.
They are sometimes compared to mini%programs.

In Swing, the Event thread is an infinite loop.

You have to call System.exit( 0 ); to actually


quit.
The Event Thread

Each pass through the event loop, Swing


looks for mouse movements, mouse button
presses, keyboard presses, etc.

If an event is found, Swing passes any


appropriate data to the component most
directly affected by the event.
Keyboard events go to the component that has “focus”.
Mouse events go to the component under the mouse !if any".
Listening for Events
You can “listen” for events in components you
create by adding “listeners”.

Swing defines a number of listener interfaces:


java.awt.event javax.swing.event
ActionListener ChangeListener

MouseListener DocumentListener

MouseMotionListener TableModelListener

WindowListener TreeModelListener

ItemListener
Listening for Events

You can tell what kind of events a component


can receive by looking for functions of the
form addXYZListener(), and examining the
type of listener the function expects as a
parameter.

addActionListener() is used by a number of


components and needs a parameter of
ActionEventListener.
Event Listeners

Any class can implement an event listener


interface.

Named inner classes are usually the best way


to implement event listeners.
Inner classes have direct access to the data stored in the outer class.
You never have to wonder where the events are handled.
Most event listeners are short functions !5 lines or less".
Event Listener Warnings

Never use anonymous classes to implement an


event listener.

Do not try to do long processing in an event


listener, or a function called by a listener.

Do not try to share listeners between


components.
A Sample Listener
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class HelloButton {
public static void main( String[] args )
{
new HelloButton();
}

HelloButton()
{
JButton hello = new JButton( “Hello, world!” );
hello.addActionListener( new HelloButtonListener() );
JFrame frame = new JFrame( “Hello Button” );
Container pane = frame.getContentPane();
pane.add( hello );
frame.pack();
frame.show();
}
A Sample Listener
private class HelloButtonListener
implements ActionListener
{
public void actionPerformed( ActionEvent e )
{
System.out.println( “The event was: “ + e );
}
}
}

The event was:


java.awt.event.ActionEvent&ACTION_PERFORMED,cmd=Hello, world!' on
javax.swing.JButton&,0,0,141x27,layout=javax.swing.OverlayLayout,alignmentX=
0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource(CompoundBor
derUIResource@1d8ff06,flags=48,maximumSize=,minimumSize=,preferredSize=,
defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.Inset
sUIResource&top=2,left=14,bottom=2,right=14',paintBorder=true,paintFocus=tru
e,pressedIcon=,rolloverEnabled=false,rolloverIcon=,rolloverSelectedIcon=,select
edIcon=,text=Hello, world!,defaultCapable=true'
Changes in the example

The code to create the UI is now in the class


constructor.
Inner classes that are not static have to be created by class
functions that are not static.

The components that are added to the frame


are created and configured before the frame is
even created.
Organizing the code to deal with only one component at a time
makes it easier to read and change.
Adapters vs. Listeners
Some listeners have many events they can
listen for.
MouseListener !5 events"
WindowListener !7 events"

Adapters are sometimes provided for these


listeners.
Implement the listener interface with empty functions.
You can subclass the adapter if you don’t want to implement the
entire listener.
Just override the functions you want to work with.
Quitting Example
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class HelloButton {
public static void main( String[] args )
{
new HelloButton();
}

HelloButton()
{
JButton hello = new JButton( “Hello, world!” );
hello.addActionListener( new HelloButtonListener() );
JFrame frame = new JFrame( “Hello Button” );
frame.addWindowListener( new HelloButtonWindowListener() );
frame.getContentPane().add( hello );
frame.pack();
frame.show();
}
Quitting Example
private class HelloButtonListener
implements ActionListener
{
public void actionPerformed( ActionEvent e )
{
System.out.println( “The event was: “ + e );
}
}

private class HelloButtonWindowListener


extends WindowAdapter
{
public void windowClosed( WindowEvent e )
{
System.out.println( “Goodbye!” );
System.exit( 0 );
}
}
}
Component Layout
A Layout Manager determines where each
component should be placed in the window
or the container.

The book has excellent examples for many of


the common layout managers:
FlowLayout places components in the window from left to right,
like a word processor.
GridLayout is like a table, all components are the same size.
Border Layout splits the area into 5 predefined spaces like a
compass.
JPanel and Nested
Containers
JPanel is an empty component that does not
have any visual representation.

JPanels are used to split one container into


smaller !more manageable" areas.

Each JPanel has its own layout manager.

You can assign a GridLayout to the JFrame,


and put a JPanel with a BorderLayout in each
cell.
Nested Container
Example
JPanelExample()
{
JFrame frame = new JFrame( “JPanel Example” );
frame.getContentPane().setLayout( new GridLayout( 2, 2 ) );

for( int i = 0; i < 2; i ++ ) {


for( int j = 0; j < 2; j++ ) {
JPanel p = new JPanel();
p.setLayout( new BorderLayout() );
p.add( new JButton( “North” ), BorderLayout.NORTH );
p.add( new JButton( “South” ), BorderLayout.SOUTH );
p.add( new JButton( “East” ), BorderLayout.EAST );
p.add( new JButton( “West” ), BorderLayout.WEST );
p.add( new JButton( “Center” ), BorderLayout.CENTER );
frame.getContentPane().add( p );
}
}
frame.pack();
frame.show();
}
Nested Container
Example
BoxLayout

BoxLayout is an easy to use layout manager


that allows you to create complex
containment schemes.

It is more flexible than the other managers,


but only slightly more complex than the
FlowLayout.

It requires you to use nested containers.


BoxLayout Example
BoxLayoutExample()
{
JPanel p1 = new JPanel();
p1.setLayout( new BoxLayout( p1, BoxLayout.X_AXIS ) );
p1.add( Box.createHorizontalGlue() );
p1.add( new JButton( “Right Aligned” ) );
JPanel p2 = new JPanel();
p2.setLayout( new BoxLayout( p2, BoxLayout.X_AXIS ) );
p2.add( Box.createHorizontalGlue() );
p2.add( new JButton( “Center Aligned” ) );
p2.add( Box.createHorizontalGlue() );
JFrame frame = new JFrame( “JPanel Example” );
frame.getContentPane().setLayout(
new BoxLayout( frame.getContentPane(), BoxLayout.Y_AXIS ) );
frame.getContentPane().add( p1 );
frame.getContentPane().add( Box.createVerticalStrut( 20 ) );
frame.getContentPane().add( p2 );
frame.pack();
frame.show();
}
BoxLayout Example
Why BoxLayout is a
better layout

You can set three size attributes of Swing


Components: Minimum, Preferred, and
Maximum

Unlike most layout managers, BoxLayout


respects the size attributes of its components.

You get the a lot of flexibility with only a few


functions.
Borders
BorderFactory allows you to create borders
for JComponent descendants !most of Swing".
Call setBorder! BorderFactory.createXYZBorder!" ";

Uses of Borders:
Excellent for debugging layout issues when you have nested JPanels
and resize problems.
Empty borders can be used to create extra spacing around
components where nothing is drawn.
Compound borders can be used to stack borders on top of each
other !for example, an empty area of 12 pixels on all sides, and then
an etched border, or another compound border".
Text Input with Swing

JTextField is a simple, single line text entry


area.

JTextArea allows multi%line input, but is much


more complex.
Text Input Example
private JTextField textField;
private JLabel echoLabel;

TextFieldExample() {
textField = new JTextField( “Enter text here...” );
echoLabel = new JLabel( “...it will echo here.” );
JFrame frame = new JFrame( “Text Field Example” );
frame.getContentPane().setLayout( new GridLayout( 2, 1 ) );
frame.getContentPane().add( textField );
frame.getContentPane().add( echoLabel );
frame.pack();
frame.show();
}
private class TextFieldListener
implements ActionListener
{
public void actionPerformed( ActionEvent e ) {
echoLabel.setText( textField.getText() );
}
}
JOptionPane
JOptionPane allows you to create simple
dialog boxes:
showConfirmDialog() presents the user with up to three choices: Yes,
No, and Cancel.
showInputDialog() gives the user a question and a text field to
enter input.
showMessageDialog() is great for reporting errors !invalid input"
and simple messages.

Each function has multiple versions, with


varying degrees of configuration.
Menu bars and Menus
JFrame and JDialog both provide the
setJMenuBar() function to specify the menu bar
for that window.

JMenuBar provides an add() function to add


JMenus.

JMenu provides an add() function for


JMenuItems, Strings, and Components.

JMenus can be added to other JMenus.


Menu Bar Example
private JFrame mbeFrame;

MenuBarExample() {
mbeFrame = new JFrame( “Text Field Example” );
mbeFrame.setJMenuBar( makeMenuBar() );
mbeFrame.getContentPane().add( new JLabel( “Other Stuff Here.” ) );
mbeFrame.pack();
mbeFrame.show();
}
private class QuitItemListener
implements ActionListener
{
public void actionPerformed( ActionEvent e ) {
if( JOptionPane.showConfirmDialog( mbeFrame,
“Do you want to quit?”, “Confirm Quit”,
JOptionPane.YES_NO_OPTION ) == JOptionPane.YES_OPTION ) {
System.exit( 0 );
}
}
}
Menu Bar Example
private JMenuBar makeMenuBar() {
JMenuItem quitItem = new JMenuItem( “Quit” );
quitItem.addActionListener( new QuitItemListener() );
JMenu fileMenu = new JMenu( “File” );
fileMenu.add( new JMenuItem( “Item 1” ) );
fileMenu.add( “Item 2” );
fileMenu.addSeparator();
JMenu fontMenu = new JMenu( “Font” );
fontMenu.add( “Times” );
fontMenu.add( “Courier” );
fontMenu.add( “Script” );
JMenu editMenu = new JMenu( “Edit” );
editMenu.add( “Undo” );
editMenu.addSeparator();
editMenu.add( fontMenu );
JMenuBar mbar = new JMenuBar();
mbar.add( fileMenu );
mbar.add( editMenu );
return( mbar );
}
Demonstrations and
Questions