Beruflich Dokumente
Kultur Dokumente
uk
www.JayDeeTechnology.co.uk
Page 1
www.PlanetJava.co.uk
www.JayDeeTechnology.co.uk
be constructed using both the AWT and Swing (although there are some limitations).
However, as the AWT knows nothing about different look and feels and mixes both
lightweight (pure Java) and heavy weight (native) components, any AWT windows may not be
consistent with the Swing windows. From the point of view of the developer, it makes little
sense to continue to use the AWT when all of the AWTs facilities (and more) are replicated in
Swing. Indeed, much of what an AWT developer already knows will go a long way to helping
them to get started with Swing as will be shown by this article.
So thats Swing, but what is its relationship to the JFC and the JDK? Essentially, Swing is a
core component of the JFC along with Java2D, Accessibility and Drag and Drop. It is the
largest element of the JFC (as it stands now) and will therefore be taken by many to equate to
the JFC. Indeed one insider has said that it is spelt JFC but pronounced Swing. However, as
can be seem from the above list, this is not the case. As this column is about Swing we will
not digress into Java2D, the Accessibility API or Drag and Drop, except to say that each is a
significant development with Java2D being a major improvement over the basic facilities in
previous version of the JDK.
So where does that leave the JDK 1.2? In many ways JDK 1.2 is the JFC plus various
enhancements which consolidate JDK 1.1. For example, JDK 1.2 includes numerous
collection classes for data structures that greatly improve on the basic set of facilities provided
with JDK 1.0 and 1.1. Equally, the performance enhancements provided will be of welcome,
however it is the Swing set of components that will grab the attention.
Control of
User Input
Information
Model
Page 2
www.PlanetJava.co.uk
www.JayDeeTechnology.co.uk
delegates
drawing
UI
Delegate
Model
Controller
JComponent
Page 3
www.PlanetJava.co.uk
www.JayDeeTechnology.co.uk
Transitioning to Swing
In the remainder of this column we will look at how to convert a relatively simple AWT based
application to a Swing based on. The application we shall use provides a very simplistic
picture tool. However, it possesses many of the features which will be of interest to Java
developers. We shall first look at how this application is implemented in the AWT and then at
what changes we need to make to move it over to Swing (note that depending on whether
you are using the Swing release with JDK 1.1 or the JDK 1.2 release, you will need to sue
different import statements. The Swing release requires an import state of the form import
com.sun.java.swing.* compared to a JDK 1.2 import statement import java.awt.swing.*.
Through out this article we will assume that the JDK 1.2 is being used).
A swinging gallery
We are now ready to port this application to Swing. So where do we start. The first thing is to
convert class such as Frame, Button and Panel to their Swing equivalents. In general the
graphical components in Swing are prefixed by a J, this the Swing version of a Button is
JButton, etc. Table 1, presents some comparisons.
Table 1 : Mapping AWT to Swing components
AWT name
Button
Frame
Panel
Menu
TextField
Swing name
JButton
JFrame
JPanel
JMenu
JTextField
AWT name
CheckBox
ScrollBar
Label
List
TextArea
Swing name
JCheckBox
JScrollBar
JLabel
JList
JTextArea
You should be careful of merely assuming that the Swing versions of components will be
exactly the same as the AWT versions. In general they provide more functionality. In some
cases they have changed their names because their functionality has changed so much (for
example, FileDialog is now JFileChooser). In other cases new classes have been
introduced to provide a better way of implementing features. For example, to generate a radio
button in the AWT a developer used a CheckBox object within a check box group, in Swing
we now have the JRadioButton class.
So far so good, we have now changed all the Buttons, Panels and Frames to become
JButton, JPanel and JFrame. Next we need to obtain the top level JFrames content pane.
For example, this is done in listing 3 in the following manner: Container pane =
getContentPane(). This is new. You never had to get hold of a frames content pane in the
AWT. Indeed, did a frame have a content pane in the AWT? SO what is this content pane? In
Swing JFrame, JDialog and JApplet are top-level containers. These top-level containers
provide the framework within which other (lightweight) components can draw themselves.
This framework is implemented by the content pane. Without a content pane lightweight
components such as JButton, JLabel etc. could not be drawn. Thus lightweight components
must be drawn within some form of top-level container (or within a component which is
eventually drawn within a top-level container). Effectively, the content pane is the link to the
host platform, it is a heavyweight AWT component (in fact an instance of Container) which
can render itself on the host platforms windowing system.
Once you have got hold of the JFrames content pane, you must then make sure that all the
components displayed within the window are added to the content pane and not the JFrame.
For the gallery application (now named SwingGallery) the structure of the application is
therefore that illustrated in figure 4.
Page 4
www.PlanetJava.co.uk
www.JayDeeTechnology.co.uk
JFrame
content pane
JPanel
PicturePanel
JButton
(load)
JButton
(exit)
JButton
Page 5
www.PlanetJava.co.uk
www.JayDeeTechnology.co.uk
PicturePanel picturePanel;
public static void main(String args []) {
new SwingGallery("Swing Gallery");
}
public SwingGallery(String label) {
super(label);
// Need to get the JFrames content pane
Container pane = getContentPane();
addWindowListener(new WindowHandler());
// Now use a JPanel instead of Panel (can set a border)
JPanel p = new JPanel();
p.setBorder(BorderFactory.createEtchedBorder());
ButtonPanelController bpc = new ButtonPanelController();
// Now use JButtons instead of Button which can take an icon
ImageIcon buttonIcon = new ImageIcon("load.gif");
JButton b = new JButton("Load", buttonIcon);
// Can now set a key board short cut and tool tips
b.setKeyAccelerator('l');
b.setToolTipText("Loads a picture");
b.addActionListener(bpc);
p.add(b);
b = new JButton("Exit");
b.setKeyAccelerator('x');
b.setToolTipText("Exits from application");
b.addActionListener(bpc);
p.add(b);
// VERY IMPORTANT: Now add the panel to the content pane
pane.add("North", p);
picturePanel = new PicturePanel();
// Now use a JScrollPane
JScrollPane scrollPane = new JScrollPane(picturePanel,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
);
pane.add("Center", scrollPane);
// Some extra bits to show some of Swings look and feel
// Illustrate use of different look and feel using radio buttons
JCheckBox motifButton = new JCheckBox("Motif");
motifButton.setActionCommand("motif");
motifButton.setToolTipText("Selects the Motif look and feel");
JCheckBox basicButton = new JCheckBox("Basic", true);
basicButton.setActionCommand("basic");
basicButton.setToolTipText("Selects the Basic look and feel");
RadioButtonHandler rbh = new RadioButtonHandler(this);
motifButton.addItemListener(rbh);
basicButton.addItemListener(rbh);
ButtonGroup buttonGroup = new ButtonGroup();
Page 6
www.PlanetJava.co.uk
www.JayDeeTechnology.co.uk
buttonGroup.add(motifButton);
buttonGroup.add(basicButton);
p = new JPanel();
p.setAlignmentX(LEFT_ALIGNMENT);
p.setBorder(new BevelBorder(BevelBorder.RAISED));
p.add(motifButton);
p.add(basicButton);
pane.add("South", p);
pack();
setVisible(true);
}
// Inner class to handle window events
class WindowHandler extends WindowAdapter {
public void windowClosing(WindowEvent event) {
System.exit(0);
}
}
// Inner class to handle button events
class ButtonPanelController implements ActionListener {
public void actionPerformed(ActionEvent event) {
String cmd = event.getActionCommand();
if (cmd.equals("Load")) {
// Now need to use Swing file dialog
JFileChooser fd = new JFileChooser(".");
fd.setPrompt("Select Image");
fd.showDialog(SwingGallery.this);
String filename = (fd.getSelectedFile()).getName();
picturePanel.setImageFilename(filename);
} else {
System.exit(0);
}
}
}
// New inner class to handle radio button look and feel options
class RadioButtonHandler implements ItemListener {
private JFrame frame;
public RadioButtonHandler (JFrame frame) {this.frame = frame;}
public void itemStateChanged(ItemEvent event) {
String lookAndFeel;
String option = ((JCheckBox)event.getItem()).getActionCommand();
if (option.equals("motif")) {lookAndFeel =
"java.awt.swing.motif.MotifLookAndFeel";
} else {lookAndFeel = "java.awt.swing.basic.BasicLookAndFeel";}
// This is where the look and feel gets set
try {
UIManager.setLookAndFeel(lookAndFeel);
SwingUtilities.updateComponentTreeUI(frame);
frame.pack();
} catch (Exception exc) {
System.err.println("could not load LookAndFeel: " + lookAndFeel);
}
}
Page 7
www.PlanetJava.co.uk
www.JayDeeTechnology.co.uk
}
}
We now need to look at the PicturePanel class. In Swing we can make this class much
simpler. Of course we need to change references to Panel to JPanel, however, we can now
use the JButton class to display the image and the ImageIcon class to load it. Thus out
JPanel merely creates a JButton object using only an Image (i.e. no string label) and adds it
to itself. When a new image is to be displayed a new JButton object is created with the new
image. The Swing version of the PicturePanel class is presented in Listing 5.
Listing 5: The Swing version of PicturePanel
package swing.gallery;
import java.awt.swing.*;
// Now make this a subclass of JPanel
public class PicturePanel extends JPanel {
private String imageFilename;
private JButton image;
public void setImageFilename(String filename) {
imageFilename = filename;
loadImage();
}
// Use a button with the image as an icon - a lot easier
private void loadImage() {
if (image != null) remove(image);
ImageIcon picture = new ImageIcon(imageFilename);
image = new JButton(picture);
add(image);
}
}
The result of running our new Swing based application is presented in figure 5 using both the
basic and motif look and feel.
Page 8
www.PlanetJava.co.uk
www.JayDeeTechnology.co.uk
Things to remember
This section briefly summarises some of the things you need to remember when you are
porting an AWT interface to Swing (or writing a Swing interface from scratch):
1. You need to get hold of the top-level components content pane before you can add
anything to it. You can do this using the getContentPane() method.
2. All Swing components have an associated model. For buttons and label etc. this model is
created for you, for more complex components you need to create it before creating the
GUI component (on it).
3. You need to be careful about mixing lightweight Swing components with heavyweight
AWT components. This can cause problems with the use of different look and feels as
well as refreshing displays.
4. We have ignored whole areas of Swing in this article. For example, the buttons in the
SwingGallery application might well have been better implemented as a dockable menu
bar (see java.awt.swing.JToolBar).
5. At present you will need to import Swing from different places depending on whether you
are using Swing with JDK 1.1 or JDK 1.2.
6. Swing has not been fully released yet and as such is subject to change and possesses a
number of undesirable features.
References
[1] Krasner, G. E. and Pope, S. T. (1988). A Cookbook for Using the Model-View Controller
User Interface Paradigm in Smalltalk-80, JOOP 1(3), pp. 2649.
[2] Hunt, J. E., Constructing modular user interfaces in Java, Java Report, Vol. 2(8), pp. 25
32, Sept 1997.
Online References
The Swing home pages: http://java.sun.com/products/jfc/swingdoc-current/index.html
The JDK 1.2 see: http://java.sun.com/???
The Swing Connection: http://java.sun.com/products/jfc/swingdoc-current/doc/index.html
The JFC Home Page: http://java.sun.com/products/jfc/index.html
The Java Tutorial: Using the JFC "Swing" Release:
http://java.sun.com/docs/books/tutorial/post1.0/ui/swing.html
Page 9