Download lecture12intro_GUIcontd

Document related concepts
no text concepts found
Transcript
Nota Bene
This lecture presentation contains a number of
"hidden" slides. Feel free to read, study and learn
from them on your own! (I openned them all)
Today's Plan for Fun
• Events
– What is an event?
– Simple (?) Example
• Swing Components
– JFrames
– JComponents
– An example
– Swing Component Design (MVC/UI-Delegate)
Events
• Behind the scenes the Java runtime environment is monitoring lots
of things
• When any of a number of different things happen an event is said
to occur. Sometimes the terminology is "An event gets fired"
• Examples of the types of things that can "fire" events
– Pressing a key on the keyboard
– Clicking on a component (like a button)
– Entering a component with the mouse pointer
– Have a timer "time-out"
Events
• Moving the mouse around any reasonably complicated GUI can
literally cause hundreds if not thousands of events to occur
• They will be ignored except for the ones that you tell Java that you
are interested in doing something about
• Java maintains a data structure of all the events that you have
decided to handle and looks up events and does what you tell it to
do.
Remember this???
import java.awt.*;
public class HelloGUI {
public static void main (String[ ] arg) {
System.out.println
("About to make GUI");
Frame f = new Frame ("Hello GUIs");
f.setSize( 200, 200 );
f.show();
System.out.println
("Finished making GUI");
}// main
}// class HelloGUI
What didn't work???
Making it work
• Determine which event occurs when the "Close the Window"
button is pressed
– The API is your friend
– The lecture notes are your friend
– Hint: In this case it's an event called "Window Closing"
• Decide what class is going to handle this event
– It might be the actual class which has the window
– It can be any other class
• Write the method (and class?) that will handle the event. When this
event occurs Java is going to go to the class that you identify as
the event handler or Listener. It will look for a method called:
public void windowClosing(WindowEvent e)
• Jave will be sorely annoyed if this class doesn't have this method.
How might the designers of Java guaranteed that you will
implement this method?
An Interface!!!
// Note: found in java.awt.event
public abstract interface WindowListener
extends EventListener
{
void windowActivated(WindowEvent e);
void windowClosed(WindowEvent e);
void windowClosing(WindowEvent e);
void windowDeactivated(WindowEvent e);
void windowDeiconified(WindowEvent e);
void windowIconified(WindowEvent e);
void windowOpened(WindowEvent e);
}
So we could write a class like this
import java.awt.*;
import java.awt.event.*;
public class Handler implements WindowListener
{
public void windowActivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e)
{
Window w = e.getWindow();
w.setVisible(false);
w.dispose();
System.exit(0);
}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
}
Making it work II
• Register the listener with Java. That is, tell Java in which class the
method will be located to run when the Window Closing Event
occurs.
Registration
import java.awt.*;
public class HelloGUI
{
public static void main (String[ ] arg) {
Handler h = new Handler();
System.out.println ("About to make GUI");
Frame f = new Frame ("Hello GUIs");
f.setSize( 200, 200 );
f.addWindowListener(h);
f.show();
System.out.println("Finished making GUI");
} // main
} // class HelloGUI
Demonstration
Diagramatically
Class Pool
class HelloGUI
main {
Frame f
Handler h
}
class Frame
class Handler
Interface WindowAdapter
Frame
Instance
Handler
Instance
Key Ideas
• Determine which event occurs
• Decide what class is going to
handle this event
• Write the method (and class?)
that will handle the event.
• Register the listener with Java.
Questions?
Very important that you understand this simple
example to understand the concepts that follow.
Potential Points of Perplexion
• What exactly is the listener? Is it the component getting clicked
on?
– No, the listener is the object that contains the method that Java
will call when the event happens.
– You must tell the component getting clicked which object that is
by registering: addWindowListener...
– As we will see it could be the same!!!
• How will I know what type of listener to use?
– There are only so many
– The API
– Lecture/Instructor/Recitation/TA/etc.
– Experience!
• What about all those other window things (e.g. windowActivated)
– We actually did implement them
– We said: Don't do anything!
Questions?
Today's Plan for Fun
• Events
– What is an event?
– Simple (?) Example
• Swing Components
– JFrames
– JComponents
– An example
– Swing Component Design (MVC/UI-Delegate)
Recall
Earlier, we cautioned about
the existence of two toolkits
in Java for creating GUIs:
AWT
Swing
Java’s GUI Capabilities
Java provides essentially two related toolkits for
making GUIs:
1. The Abstract Windowing Toolkit (“AWT”), and
1.
2. The Java Foundation Classes (“Swing”)
2.
Swing is merely a new, improved version of the AWT,
and still uses some of AWT’s features.
Today, we examine a few Swing components.
The goal is to learn how Swing components in general are
designed, so that you can make better use of the API.
That Which Swings
In 1997, Sun announced a new graphical toolkit for Java called
the “Java Foundation Classes”, or “JFC”.
This term is usually pronounced “Swing”.
The JFC/Swing classes provide well designed, powerful
widgets for GUI developers.
Let’s take a look . . .
JFC/Swing
“Now it gets interesting . . . “
0.
(De)Motivation
Historical Problems with AWT
•
•
All AWT components required runtime peer resources
– slow on some platforms (notably Windows)
– portability problems (slightly different look, some behaviors different)
– least common denominator phenomenon: If one OS (e.g., Windows)
did not support a widget, the entire AWT had to suffer without it.
Limited AWT widget library
– addressed somewhat by JDK 1.1b3+, which allowed subclassing of
components, or “lightweights”
java.awt.Button
ButtonPeer
AWT components required
native “peer” methods to
render and operate--many steps!
WinNT
ButtonPeer
MacOS
ButtonPeer
Motif
ButtonPeer
File Edit
Help
CLICK ME
Slow & Inflexible!
Stop-gap remedies for JDK 1.1b3+
•
Developers avoided a few AWT limitations through:
– Pervasive use of lightweights
– e.g., tooltip simulation through threads/windows/components
– extensive coding around rigid look
(Layering of
– use of layered gifs
components
Bottom line: Making stuff look cool
or satisfying a clients request
could be a nightmare!
File Edit
(Tooltips required
threads,
window
subclasses &
extensive
event handling)
Help
CLICK ME
Tooltip
requires layout
subclasses)
(Menu bars limited;
no images possible
without *extensive*
simulation through
components)
(Image buttons required
component subclassing,
methods to handle ‘click’
look, as well as event
handlers)
Introducing Swing/JFC
•
Sun addressed problems with Java Foundation Classes (JFC) a/k/a Swing
•
Key elements:
– No reliance on native peers; the JVM does the work, and is faster
– Swing completely controls look and feel of all components:
• PLAF, or “pluggable look and feel”
– Superior design:
File Edit
Help
CLICK ME
Fast, flexible, extensible!
javax.swing.JButton
Swing Packages
•
•
•
All the new Swing components and classes need a home. Where?
A subject of great debate!
For JDK 1.1, Sun used “com.sun.java.swing”; developers
revolted(başkaldırmak).
• Problem: developers complained this “com” designation was not
appropriate for “core” class--something part of language.
Solution:
Why “javax”?
* logical grouping
javax.swing.*
* minimizes transition
costs
* most developers
happy with it
Denotes ‘extension’ package that
has migrated to core status
* helps maintain
existing JDK 1.1 code
(cf. MFC lib breaks)
Overview of JFC/Swing Packages
•
•
•
•
javax.swing.plaf
javax.swing.plaf.basic
javax.swing.plaf.metal
javax.swing.plaf.multi
• javax.swing
• javax.swing.table
• javax.swing.tree
• javax.swing.border
• javax.swing.colorchooser
• javax.swing.filechooser
•
•
•
•
javax.swing.text
javax.swing.text.html
javax.swing.text.html.parser
javax.swing.text.rtf
• javax.swing.event
• javax.swing.undo
Overview of the Overview
Packages to
control the
“look and feel”
of Swing
Text-based widgets
(including html/rtf display)
Components,
including
“aggregate”
or complex
components
New event packages
Getting into the Swing
•
•
•
Download from www.javasoft.com
Swing works with JDK 1.1 and JDK 1.2
– JDK 1.1 requires “swingall.jar” file in the CLASSPATH
– For JDK 1.2, it’s in the soup (no CLASSPATH settings)
– JDK 1.2 will also run all JDK 1.1 code (~ 20% faster!)
Thus, even older JDKs can make use of Swing, with a CLASSPATH setting.
import com.sun.java.swing.*;
import javax.swing.*;
AWT
AWT
JDK 1.1
Swing Classes
classpath
JDK 1.2
swingall.jar
1.
Short Examples
Short Example: Old AWT
import java.awt.*;
public class HelloWorld extends Frame {
public Button bOld;
//public Panel p;
public HelloWorld() {
bOld = new Button ("Good Bye");
We comment most of
//p = new Panel();
this out for now; AWT
//p.add(bOld);
lets us add directly
//this.add(p);
to the Frame.
this.add(bOld);
/* note the addition directly to the Frame */
this.pack();
}
public static void main(String arg[]){
/* note lack of listener; this is a demo */
new HelloWorld().show();
}
}// class HelloWorld
Hello Swing, Good Bye AWT
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
Note Swing
public class HelloWorld extends JFrame {
components
Button bOld; public JButton bNew;
public JPanel p;
public HelloWorld() {
bNew = new JButton("Hello");
bOld = new Button ("Good Bye");
Note addition of
p = new JPanel();
components to
p.add(bNew); p.add(bOld);
JPanel’s ‘content
pane’
this.getContentPane().add(p);
this.pack();
}
public static void main(String arg[]){
new HelloWorld().show();
SEE CAUTIONARY NOTE RE:
}
Mixing light and heavyweight
}// class HelloWorld
components!
What’s the Big Deal?
•
•
HelloWorld looks similar to AWT. Why switch to JFrame, JButton,
JPanel, etc?
Benefits:
– speed
– lightweight flexibility (transparency, non-rectangular shape)
– pluggable look and feel
– automatic double buffering with many J- components.
– additional functionality (e.g., tooltips, etc.)
I’m lightweight,
pluggable, extensible
and fast. The VM
draws me.
I need Windows™
to be visible and
‘toggle’. I’m slow.
Widget Example: JButtons
•
The java.swing.JButton class implements a “state version” of
a java.swing.AbstractButton. Many methods come from the
abstract class:
– A variety of constructors (Strings, Icons, etc.);
– setRolloverEnabled(boolean);
– setIcon(Icon);
– setRolloverIcon(Icon);
– setActionCommand(String); -- an extra String tacked onto
the event that gets fired!
– setContentAreaFilled(boolean) -- transparency for icons!
– setModel(ButtonModel); -- sets the ‘type’ of Button (you
can define your own Button behaviors!)
– setMnemonic(char/int); -- set mnemonics for button
Lesson: Check the API
for useful behaviors.
Cool Buttons
import javax.swing.*;
public class HelloWorld2 extends JFrame {
public JButton bNew;
public JPanel p;
public HelloWorld2() {
bNew = new JButton("New Document", new
ImageIcon("Document.gif"));
bNew.setRolloverEnabled(true);
bNew.setRolloverIcon
(new ImageIcon ("New.gif"));
p = new JPanel();
p.add(bNew);
getContentPane().add(p);
this.pack();
}
public static void main(String arg[ ]) {
new HelloWorld2().show(); }
}// class HelloWorld2
Images from disk:
Sets icon and
rollover Icon.
Note: Icon constructor
took String argument,
and automatically
loaded image
Demonstration
Why getContentPane() ?
•
The HelloWorld example required us to call getContentPane()
before “add()”ing an object to the JFrame:
myFrameInstance.getContentPane().add(myComponent);
Usually
“this”
Required of
JFrame, JDialog
and JInternalFrame
instances
E.g.,
“myJButton”
• This differs from traditional AWT container additions, were
we simply call “add”, passing in the component.
• Let’s cut a JFrame open to find out why . . .
A JFrame Autopsy
“The Pop Tart / Sandwich Duality”
JLayeredPane
Menu
ContentPane
A java.awt.Frame is
composed of a single
container--the Frame object
itself. It is flat as a pop tart.
JPanel
A javax.swing.JFrame is
composed of a
transparent “glassPane”
surface, and an inner
Jpanel with Contents and
Menu
JFrame Class View
AWT
Component
GlassPane
Frame
Container
ContentPane
JComponent
contains
JFC
JRootPane
manages
JMenuBar
JFrame
The JRootPane is a container with
a JLayeredPane (holding the Menu
and ContentPane) and a
Component GlassPane. It serves
as base for numerous classes.
JLayeredPane
JRootPane: The Content Pane
The JRootPane contains only two components:
the JLayeredPane and
the Component GlassPane
Its layout manager ignores all attempts to add new components.
Instead, one must add to the JRootPane’s ContentPane, found
inside the JLayeredPane.
A call to getContentPane() returns an instance of the
ContentPane.
JRootPane: The Glass Pane
public Component getGlassPane();
public void setGlassPane(Component);
JFrame Blue Print
We can use the top “glassPane”
as a drawing area. Since it spans
the entire JFrame, we can draw on
top of menu bars, and every
component.
The JPanel has a remarkable
layering feature, allowing us to
stack and shuffle components.
public JPanel getContentPane();
JFrame Disposal
•
JFrame allows you to configure how it responds to closure.
– Default: hides JFrame on closure attempt.
– To modify: invoke setDefaultCloseOperation().
– E.g.,:
MyJFrameInstance.setDefaultCloseOperation
(WindowConstants.DO_NOTHING_ON_CLOSE);
/* behaves just like java.awt.Frame */
– other constants in javax.swing.WindowConstants:
– HIDE_ON_CLOSE - invokes any registered WindowListener
objects, then hides. This is default behavior.
– DISPOSE_ON_CLOSE - invokes any registered WindowListener
objects, and then disposes.
Questions?
JComponent: The Generic Widget
•
The JComponent provides the basis for all Swing components.
• JComponent extends java.awt.Container, making all Swing
components large, powerful widgets. (Also, all Swing
components are also containers--even if you wouldn’t normally
place things in them. E.g., JButton)
•
In turn, JComponent is subclassed by numerous widgets. Thus,
composition is favored or inheritance for widget manipulation.
JComponent
Since JComponent is the basis for most Swing components, all Swing
widgets have the following general features:
Borders
-- JComponent derived classes can have borders
Accessibility
-- JComponents use Swing’s accessibility features to provide
additional information about the widget.
Tooltips
-- JComponents can have time sensitive tooltips.
Double Buffering
-- By default, Swing components have double buffering built in
Serialization
-- Ability to save state to a file.
Demo: A GlassPane Example
import
import
import
public
java.awt.*;
java.awt.event.*;
javax.swing.*;
class GlassDemo extends JFrame implements ActionListener {
private boolean bGlassVisible;
private GlassPanel glass;
private JButton button;
This demo will not
be covered in class;
it is provided as an
example of how to
work with JFrames.
Here’s a simple example that
shows how to use aspects of JFrames.
Frist, we make a JFrame subclass.
We declare some instance
variables: a GlassPanel (described later),
a boolean flag for the glass panel’s
visibility, and a JButton to toggle
Glass Panel Example
import
import
import
public
java.awt.*;
java.awt.event.*;
javax.swing.*;
class GlassDemo extends JFrame implements ActionListener {
private boolean bGlassVisible;
private GlassPanel glass;
private JButton button;
public void actionPerformed (ActionEvent e){
bGlassVisible = !bGlassVisible;
glass.setVisible(bGlassVisible);
}
The actionPerformed method
merely toggles the
visibility of the glass pane
Glass Panel Example
import
import
import
public
java.awt.*;
java.awt.event.*;
javax.swing.*;
class GlassDemo extends JFrame implements ActionListener {
private boolean bGlassVisible;
private GlassPanel glass;
private JButton button;
public void actionPerformed (ActionEvent e){
bGlassVisible = !bGlassVisible;
glass.setVisible(bGlassVisible);
}
public void centerInScreen(){
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension d = tk.getScreenSize();
this.setLocation((d.width-getSize().width)/2,
(d.height-getSize().height)/2);
}
... A little magic.
(It merely centers the frame
in the screen.)
Glass Panel Example
import
import
import
public
java.awt.*;
java.awt.event.*;
javax.swing.*;
class GlassDemo extends JFrame implements ActionListener {
private boolean bGlassVisible;
private GlassPanel glass;
private JButton button;
public void actionPerformed (ActionEvent e){
A simple
bGlassVisible = !bGlassVisible;
test main
glass.setVisible(bGlassVisible);
}
public void centerInScreen(){
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension d = tk.getScreenSize();
this.setLocation((d.width-getSize().width)/2,
(d.height-getSize().height)/2);
}
public static void main(String[] args) {
new GlassDemo().show();
}
public GlassDemo () {
this.setSize(400,400);
this.getContentPane().setBackground(Color.white);
this.getContentPane().setLayout(new BorderLayout());
this.addWindowListener (new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}});
Our constructor has poor abstraction, but
is sufficient for a demonstration.
We start by setting a size, background,
layout, and a simple WindowListener
public GlassDemo () {
this.setSize(400,400);
this.getContentPane().setBackground(Color.white);
this.getContentPane().setLayout(new BorderLayout());
this.addWindowListener (new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}});
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
button = new JButton ("Toggle");
button.addActionListener(this);
p.add(Box.createHorizontalGlue());
p.add(button);
p.add(Box.createHorizontalGlue());
We add a JButton to a
containing JPanel. We make
sure it will center in the
JPanel, using ‘glue’ objects. The
same effect can be obtained with
more complicated layerings of
panels and layout managers.
public GlassDemo () {
this.setSize(400,400);
this.getContentPane().setBackground(Color.white);
this.getContentPane().setLayout(new BorderLayout());
this.addWindowListener (new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}});
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
button = new JButton ("Toggle");
button.addActionListener(this);
p.add(Box.createHorizontalGlue());
p.add(button);
p.add(Box.createHorizontalGlue());
this.getContentPane().add(p, BorderLayout.CENTER);
this.getContentPane()
.add(new JLabel("Press Button to Toggle Glass Pane"),
BorderLayout.SOUTH);
We add the panel to our
JFrame’s content pane,
along with a simple label. . .
public GlassDemo () {
this.setSize(400,400);
this.getContentPane().setBackground(Color.white);
this.getContentPane().setLayout(new BorderLayout());
this.addWindowListener (new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}});
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
button = new JButton ("Toggle");
button.addActionListener(this);
p.add(Box.createHorizontalGlue());
p.add(button);
p.add(Box.createHorizontalGlue());
this.getContentPane().add(p, BorderLayout.CENTER);
this.getContentPane()
.add(new JLabel("Press Button to Toggle Glass Pane"),
BorderLayout.SOUTH);
centerInScreen();
glass = new GlassPanel();
We then make and set
this.setGlassPane(glass);
a new glass panel for
bGlassVisible = false;
the JFrame.
} } // end of class GlassDemo
import java.awt.*;
import javax.swing.*;
public class GlassPanel extends JComponent {
final Color trans;
public GlassPanel () {
this.setOpaque(false);
// create nearly black color with transparency
trans = new Color(150,25,25,125);
}
public Dimension getPreferredSize(){
return getParent().getPreferredSize();
}
public void paintComponent(Graphics g){
g.setColor(trans);
g.fillRect(0,0,getSize().width, getSize().height);
}
} // GlassPanel
import java.awt.*;
import javax.swing.*;
public class GlassPanel extends JComponent {
final Color trans;
public GlassPanel () {
this.setOpaque(false);
// create nearly black color with transparency
trans = new Color(150,25,25,125);
}
Our GlassPanel object is merely
a JComponent subclass. It first sets
itself to be transparent, and then
creates a color with a high transparency
value, 125. (A later lecture will touch
on the Java color model. For now, the
API shows us the arguments are Red,
Blue, Green, and Alpha transparency.)
import java.awt.*;
import javax.swing.*;
public class GlassPanel extends JComponent {
final Color trans;
public GlassPanel () {
this.setOpaque(false);
// create nearly black color with transparency
trans = new Color(150,25,25,125);
}
public Dimension getPreferredSize(){
return getParent().getPreferredSize();
}
Since we’re making our own home-grown widget,
and not one found in the API, we have to let the
layout managers know how large this component
wishes to be. We simply return the size of the
parent container--meaning the GlassPanel have the
same size as its parent container.
import java.awt.*;
import javax.swing.*;
public class GlassPanel extends JComponent {
final Color trans;
public GlassPanel () {
this.setOpaque(false);
// create nearly black color with transparency
trans = new Color(150,25,25,125);
}
public Dimension getPreferredSize(){
return getParent().getPreferredSize();
}
public void paintComponent(Graphics g){
g.setColor(trans);
g.fillRect(0,0,getSize().width, getSize().height);
}
} // GlassPanel
This method defines how the component will
look. Another lecture will explore the details
of drawing in Java. For now, know that this floods
the component with colored pixels.
Overview of GlassDemo
GlassDemo
(A JFrame
subclass )
GlassPanel class
content pane (with JButton)
(Demo)
After a press, the glass pane becomes
visible, giving a hazy(bulanık)
gauze(tül) to the GUI.
3.
Design
Button Design
•
•
JButtons are a good example of the Model, View Control structure Java,
*ahem*, borrowed and modified from Smalltalk.
Let’s examine the inheritance structure of a JButton . . .
public abstract interface
javax.swing.ButtonModel
extends ItemSelectable
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.Container
hasA
|
+--javax.swing.JComponent
|
AbstractButton
+--javax.swing.AbstractButton
implements ItemSelectable,
|
SwingConstants
+--javax.swing.JButton
Defines the common behaviors
for the JButton, JToggleButton,
The ButtonModel provides the
JCheckbox, and the
state machine for Button behavior
JRadioButton classes.
Model, View, Control
• Let's say you decide to write a program that will implement a timer
• You want to be able to set the time, start and stop the timer
• You want the timer to show the time counting down plus have
something exciting happen when time is up.
• You might write a big monlithic program that would do all this and
be swell...
• Until someone wanted a version with a different display...perhaps
some LED's, perhaps a graphical widget.
• Until someone wanted a version with a different control scheme
like JButtons
MVC
• Design this timer in three distinct parts (e.g. classes!)
– Model: This is the heart of the calculation part of the timer and
is where the data is stored. The model might not know anything
about the View or the Control
– View: The view controls what the user sees (and hears). It might
run autonomously or be controlled by the Control. It might have
a reference to the Control
– Control: This is what the user interacts with to control the timer.
It may be a set of keyboard commands or a GUI or mechanical
pushbuttons. The control has references to model and the view.
MVC Relationships
View
Model m
Control c
Model
(data)
Controller
Model m
View v
Clear
Interfaces
MVC Paradigm
•
The MVC paradigm breaks applications or interfaces into three parts: the
model, the view, and the controller.
Model
A --> 25 %
B --> 60 %
C --> 15 %
Users interact with a controller (e.g.,
buttons), and make changes to the
model (e.g., data), which is then
reflected in the view (e.g., graph).
View2
View1
Pie
A
60
B
50
B
40
30
Percentage
20
10
0
A
B
B
Control
Bar
MVC Paradigm, à la Swing
•
Swing uses a simplified version of the MVC structure, called the modeldelegate
Swing
Component
View
Model
Controller
UI-delegate
MVC: Who Cares?
Helps us
understand
complex
Swing
packages
Guides future
package
development
Why does
it matter?
Allows user
customization of
model or view,
without rewriting
both
(Think of
something
else; need
four points)
MVC: Why You Care
The formal benefits of MVC will be exposed in subsequent CS
classes focused on design and OO theory.
But you should be familiar with MVC now because Swing widgets use
the UI-Delegate variation of MVC.
If you need to change something about a Swing widget, consider
whether your proposed change affects:
* The model of a widget (its state, value)
* The look of a widget (its UI delegate)
Knowing what you are changing will help you find where in the API
you must look for useful methods.
Questions
4.
Danger
Cautionary Notes: MVC & Threads
•
An artifact of the MVC (or model-delegate) structure of Swing is the
need to avoid separate threads updating the model state
•
To avoid a race condition, one should ONLY use the eventdispatching queue.
View
myThread
Which thread
finishes last?
Event Dispatcher
Model
Controller
The event-dispatching queue handles repaints, and dispatches events
to GUI component listeners.
Confused by this? The lesson is: Don’t mix Threads and Swing
unless you know what you’re doing.
Cautionary Note: Mixing Types
•
Avoid mixing light and heavy weight components.
•
Heavy weights are “opaque” -- solid & rectangular
•
Light weights are transparent, and draw themselves on top of the
heavyweight container they occupy (Frame, Jframe, Panel, etc.)
•
This can frustrate Z-order layering
•
(The slides will violate this principle only to make a point.)
Lightweight
java.awt.Component
CLICK ME
CLICK ME
Heavy weight
java.awt.Button
As designed,
and as we coded it
What shows up
Possible Solution: Use Timers
We normally think of events as user-driven actions. But the
mere passage of time is an event that Swing components can
observe--all without the use of additional threads.
Java provides the javax.swing.Timer object--something of an
‘egg timer’ that allows one to have an event fired periodically
without user interaction:
delay
Timer t = new Timer(500, this);
t.start();
Event handler
import javax.swing.*; import java.awt.event.*;
import java.awt.*;
public class StopWatch extends JLabel implements ActionListener{
int count = 0;
public StopWatch(){
super("Elapsed Time: 0 secs", JLabel.CENTER);
Timer t = new Timer(1000, this); t.start();
}
public void actionPerformed(ActionEvent e){
this.setText("Elapsed Time: " + count++ + " secs");
}
public static void main (String arg[]){
JFrame f = new JFrame();
f.setSize(300,100);
f.addWindowListener (new WindowAdapter()
{ public void windowClosing(WindowEvent e){
System.exit(0);}});
StopWatch c = new StopWatch();
f.getContentPane()
.setLayout(new BorderLayout());
f.getContentPane()
.add(c, BorderLayout.CENTER);
f.show();
} }
Questions?