CIS 17 Java Programming
Graphical User Interfaces
Agenda ●
History
●
Basic GUI code
●
Events
●
Listeners
●
Inner Classes
●
Drawing
The March of AWTs ●
●
●
●
The Java 1.0 Abstract Windowing Toolkit (AWT) was designed and built in 30 days, and it showed. Its GUI features were layered on top of the native system. The Java 1.1 AWT was significantly improved. A new event model was introduced and “lightweight” components were added. Java 2 completely replaced (almost) the AWT with the Swing library. All Swing components are lightweight.
Java Foundation Classes ●
The JFC is a loose collection of standard Java APIs for client-side GUIs and related tasks. ●
AWT: rudimentary graphics and GUI capabilities, largely superseded in Java 1.2
●
Swing: advanced GUI toolkit written in pure Java
●
Java 2D: advanced graphics built upon the AWT
●
Printing: also built upon the AWT
●
Data Transfer: cut-and paste and drag-and-drop
●
Applets: technically not part of the JFC
Swing/JFC Features ●
Adding enhancements is straightforward: ●
keyboard accelerators
●
tooltips
●
embedded graphics
●
A pluggable look and feel is possible.
●
Considerable flexibility is built in.
Swing Contains: ●
Borders
●
Menus
●
Text Components
●
Buttons
●
Popup Menus
●
Text Fields
●
Checkboxes
●
Radio Buttons
●
Toolbars
●
ComboBoxes
●
Progress Bars
●
Trees
●
Image Icons
●
●
Labels
●
●
Layered Panes Internal Frames
Scrolling Support
●
Keyboard Navigation
●
Scrollbars
●
Support for Undo
●
Splitter Control
●
Custom Cursors
●
Tabbed Panes
●
LookAndFeel API
●
Lists
●
Tables
●
List Boxes
●
Text Areas
Introduction to Swing ●
●
●
Most of Swing's components begin with a J to distinguish them from AWT components. Applications are usually built within a JFrame which produces a window with the host operating system's decorations. The main() method creates an instance of the JFrame, JFrame sets its size and makes it visible.
Basic Swing ●
Create a window
●
Set the window title
●
Set its behavior on window close
●
Set the window size
●
Make the window visible
Basic Swing package demo01; import javax.swing.JFrame; public class BasicSwingTitle { public static void main(String[] args) { JFrame frame = new JFrame();
} }
frame.setTitle("Basic Swing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 300); frame.setVisible(true);
Add Components ●
Swing elements are called “components”
●
Create a component, i.e. a button JButton button = new JButton("I'm a button");
●
Add the component to the Window frame.getContentPane().add(button);
Events ●
Events are things you can detect.
●
An event signifies “when” something happens
●
They just let the program know when something happens (key press, mouse click, window close, etc.)
Capturing an Event ●
●
●
●
Some code is needed to be executed when the button is pressed: a “listener.” A button press calls the actionPerformed() method of the ActionListener interface. The programmer defines actionPerformed() to do the appropriate thing when the button is pressed. This is an example of a “callback.”
Callbacks for GUI Events ●
●
Register the implementation of an ActionListener with each button. When the button is pressed, it calls back to the ActionListener. ActionListener
Code example for listener public class Callback implements ActionListener { JFrame frame; JButton button; public static void main(String[] args) { (new Callback()).go(); } public void go() { frame = new JFrame(); button = new JButton("I'm a button"); button.addActionListener(this); frame.getContentPane().add(button); frame.setTitle("Basic Swing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 300); frame.setVisible(true); }
}
@Override public void actionPerformed(ActionEvent e) { button.setText("You pushed me!"); }
Two Buttons public class CallbackTwoButtons implements ActionListener { JFrame frame; JButton button1; JButton button2; public static void main(String[] args) { (new CallbackTwoButtons()).go(); } public void go() { frame = new JFrame(); button1 = new JButton("button 1"); button1.addActionListener(this); button2 = new JButton("button 2"); button2.addActionListener(this); frame.getContentPane().add(button1); frame.getContentPane().add(button1); frame.setTitle("Basic Swing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 300); frame.setVisible(true); }
}
@Override public void actionPerformed(ActionEvent e) { button1.setText("You pushed a button"); }
Layout Example .... public class BorderLayoutExample implements ActionListener { JFrame frame; JButton buttonWest; JButton buttonEast; JButton buttonNorth; JButton buttonSouth; JButton buttonCenter; public static void main(String[] args) { (new BorderLayoutExample()).go(); } @Override public void actionPerformed(ActionEvent e) { ((JButton) e.getSource()).setText("You pushed me"); }
.... Layout Example .... public void go() { frame = new JFrame(); buttonWest = new JButton("West"); buttonWest.addActionListener(this); buttonEast = new JButton("East"); buttonEast.addActionListener(this); buttonNorth = new JButton("North"); buttonNorth.addActionListener(this); buttonSouth = new JButton("South"); buttonSouth.addActionListener(this); buttonCenter = new JButton("Center"); buttonCenter.addActionListener(this); frame.getContentPane().add(BorderLayout.WEST, buttonWest); frame.getContentPane().add(BorderLayout.EAST, buttonEast); frame.getContentPane().add(BorderLayout.NORTH, buttonNorth); frame.getContentPane().add(BorderLayout.SOUTH, buttonSouth); frame.getContentPane().add(BorderLayout.CENTER, buttonCenter);
}
}
frame.setTitle("Border Layout"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(600, 300); frame.setVisible(true);
.... Layout Example
What if ... ●
You want to have to completely different actions that affect another component in the window?
Callbacks for GUI Events (part 2) ●
●
An inner class may be used to implement the ActionListener. ActionListener The inner class is a closure, so it captures a connection to the outer class and can manipulate the outer class.
Inner Classes ●
●
●
●
They are a unique and fundamental feature of the language. The Swing GUI event model is usually implemented using inner classes, More is accomplished than merely nesting classes within other classes. Beside providing hiding and code organization: ●
●
Inner class objects have full access to their enclosing objects. They replace pointers in callback mechanisms.
Anonymous Inner Classes public void go() { frame = new JFrame(); button1 = new JButton("button 1"); button1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { textarea.setText("Action1: You pushed a button"); } }); button2 = new JButton("button 2"); button2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { textarea.setText("Action2: You pushed a button"); } }); textarea = new JTextArea(); frame.getContentPane().add(BorderLayout.WEST, button1); frame.getContentPane().add(BorderLayout.EAST, button2); frame.getContentPane().add(BorderLayout.CENTER, textarea);
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 300); frame.setVisible(true);
Anonymous Inner Classes ●
●
●
Used when a single instance of an inner class is needed. A convenient but somewhat cryptic shorthand is used. Code generation tool like GUI builders often use Anonymous Inner Classes.
The Syntax extends or implements is implied.
button1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { textarea.setText("Action1: You pushed a button"); } });
The Link to the Outer Class ●
●
●
An object of an inner class has a link to the enclosing object that made it. This is similar in functionality to the this reference. The inner object can access members of the enclosing class without any special qualifications. A sort of multiple implementation inheritance is possible and much safer than in C++.
Using .this public class DotThis { void f() { System.out.println("DotThis.f()"); } public class Inner { public DotThis outer() { return DotThis.this; // A plain "this" would be Inner's "this" } } public Inner inner() { return new Inner(); } public static void main(String[] args) { DotThis dt = new DotThis(); DotThis.Inner dti = dt.inner(); dti.outer().f(); } }
Using .new public class DotNew { public class Inner {} public static void main(String[] args) { DotNew dn = new DotNew(); DotNew.Inner dni = dn.new Inner(); } }
Multiple Implementation Inheritance ●
●
●
●
Each inner class can independently inherit from an implementation and multiple inner classes can be created. Thus, the inner class is not limited by whether the outer class is already inheriting from an implementation. The technique is to inherit in an inner class and pass its object to a method expecting an outer class object. With concrete or abstract classes, inner classes are the only way to produce the effect of “multiple implementation inheritance.”
Multiple Implementation Inheritance class D {} abstract class E {} class Z extends D { E makeE() { return new E() {}; } } public class MultiImplementation { static void takesD(D d) {} static void takesE(E e) {} public static void main(String[] args) { Z z = new Z(); takesD(z); takesE(z.makeE()); } }
Drawing examples
class MyDrawPanel extends JPanel { public void paintComponent(Graphics g) { int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255); Color randomColor = new Color(red, green, blue);
}
}
g.setColor(randomColor); g.fill3DRect(10, 50, 100, 150, true);
Copyright 2009 David Pearson Released under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States license http://creativecommons.org/licenses/by-nc-sa/3.0/us/