Sie sind auf Seite 1von 9

www.PlanetJava.co.

uk

www.JayDeeTechnology.co.uk

Putting the Swing into Java


Dr. John Hunt,
JayDee Technology Limited
Minerva House
Lower Bristol Road
Bath, BA2 9ER
Tel: 01225 789255
Fax: 0870 0548872
Email: john.hunt@jaydeetechnology.co.uk
By now may of you will have heard of the Java Foundation Classes (JFC), Swing and the 1.2
release of the Java Developers Kit (JDK). However, many of you wont be sure of the
relationships between Swing, JFC and the JDK nor indeed what Swing actually provides. This
column cuts through the hype and shows you what Swing will mean for you.

Swing, the JFC and the JDK


Lets start by talking about Swing. What is it? It has been stated that the overall goal of the
Swing project was to build a set of extensible GUI components to enable developers to more
rapidly develop powerful Java front ends for commercial applications (see
http://java.sub.com/products/jfc/swingdoc-static/swing_arch.html). Thats all well and
good, but what does it mean to you and me? In real terms, it means that Swing provides a set
of graphical components which allow user interfaces to be constructed which provide
commercial quality (and functionality) with the minimum of effort. For example, many users
are now familiar with the idea of brief reminders being displayed when they leave their cursor
over a button for a short period. In Swing, these are referred to as tool tips and are simple and
straightforward to implement. Prior to Swing, however, the equivalent functionality would have
to have been provided by the developer themselves catching mouse events, waiting a period
of time and then popping up a small window with the tool tip displayed in side it. None of this
would have been trivial.
What else does Swing provide? Firstly, all components in Swing are 100% pure Java
(referred to as lightweight). This means that the windows should look the same whatever
platform they are on and should be easier to maintain (for Sun). As all graphical components
are lightweight, their appearance is controlled purely by the Java code (without the need for
platform dependent peers as in JDK 1.0 and 1.1). In swing, a separate user interface view
component performs the actual rendering of the component on the screen. This allows
different views to be plugged in. This in turn allows the idea of different looks and feels. This
means that it should be possible for a Unix developer to select the Win95/NT look and feel
and see what the interface would look like on that platform. It also means that it is easier to
deploy the same software on different platforms, but with interfaces that match the interface
manager on that particular platform. This separation of view form the actual component is
based on a modified version of the Model-View-Controller architecture (described later).
Swing also provides a greatly increased set of facilities for graphical user interfaces, including
trees, icons on buttons, dockable menus bars, menus with icons, borders and improved
support for fonts and colours.
So does this mean that the AWT (The Abstract Window Kit) of version 1.0 and 1.1 of Java is
being thrown out of the window? Not exactly, the AWT will still be available and systems can

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.

What is the MVC


We have already said that Swing is based on a modified version of the Model-View-Controller
(MVC) architecture. So what is the MVC? The MVC is not a new idea, it originated in
Smalltalk, but the concept has been used in many places. The intention of the MVC
architecture is the separation of the user display, from the control of user input, from the
underlying information model as illustrated in Figure 1 [1]. This is often referred to as modeldriven programming (i.e. the separation of GUIs from the data the present). There are a
number of reasons why this is useful:

reusability of application and / or user interface components,


ability to develop the application and user interface separately,
ability to inherit from different parts of the class hierarchy.
ability to define control style classes which provide common features separately from
how these features may be displayed.
Display/
View

Control of
User Input

Information
Model

Figure 1: The Model-View-Controller architecture


This means that different interfaces can be used with the same application, without the
application knowing about it. It also means that any part of the system can be changed
without affecting the operation of the other. For example, the way that the graphical interface
(the look) displays the information could be changed without modifying the actual application
or how input is handled (the feel). Indeed the application need not know what type of interface
is currently connected to it at all. Prior to Swing it was certainly possible to build GUIs based
on the MVC in Java (see [2]). However, Swing makes the concept of separating the data from
the display and control fundamental to its operation.

Page 2

www.PlanetJava.co.uk

www.JayDeeTechnology.co.uk

Swinging the MVC into action


Swing uses a modified version of the traditional Model-View-Controller architecture. This is
because in practice the view and the controller need to be tightly bound. Indeed, in Smalltalk
it was common to find that many classes in the view hierarchy had associated classes in the
controller hierarchy and that if you used on particular view, then you had to use the
associated controller. For myself, I have found over the last year or so, that I have moved to
defining my controllers as inner classes to my views so that while I am separating them
logically, they are directly tied together. This is essentially the conclusion which the Swing
development team came to. Thus in Swing there is a model object (for holding the data) and a
UI object for managing the view and the control. For example, even a Button has a separate
model, in the case of the class java.awt.swing.JButton, any model used must implement the
java.awt.swing.ButtonModel interface.
However, even this description fails to capture a subtlety introduced by Swing UI
delegates. In order to allow different looks and feels to be plugged in, each view controller
combination actually as a UI delegate associated with it. It is the UI delegate which actually
draws the component, although it is the component itself which is responsible for handling the
display and user input (see fig 2).
View

delegates
drawing

UI
Delegate

Model
Controller

JComponent

Figure 2 : The modified MVC in Swing


In Fig 2, the data specific Model is separated from the JComponent (the root of many of
Swings GUI components) which possesses both the view and the controller. In turn the
controller uses a separate UI delegate to actually draw the component in a window. Thus
Swing both provides leverage for model-driven programming and for pluggable look and feels.
So what does this mean for the developer? Does it mean that to use a button you must first
create a model of the data displayed by a button? No, in the case of simple components such
as buttons and labels, when you construct the GUI component an appropriate model is
created automatically. However, for more complex GUI components such as trees, you first
need to create the model (in terms of DefaultMutableTreeNodes) and then instantiate the
JTree GUI component on top of it. The JTree GUI component then displays the information
held in the model.
Figure 3: The SimpleGallery application

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

Figure 4 : The structure of the SwingGallery GUI


For the main SwingGallery class, we can now start to think about taking advantage of some
of the new features of Swing to improve the look and feel of our application. For example, we
can add icons to our buttons. This is very easy to do, the ImageIcon class can be used to
create an image which can be used as an icon for a button. One of the constructors for this
class takes a string specifying the location of the image to use (for example, ImageIcon
buttonIcon = new ImageIcon("load.gif");). Now we need to modify the constructor used to
create the actual button so that the newly created icon is passed to it as one of its parameters
(such as, JButton b = new JButton("Load", buttonIcon);) and that is all there is too it. We
can also add key board short cuts using the setAcceleratorKey(char) (or
setMnemonic(char) if you are using the Swing release rather than the JDK 1.2
setMnemonic was omitted from that release by accident!). Finally, we can also add tool tips
to buttons using the setTooTip(String) method (for example, b.setToolTipText("Loads a
picture");).
For the SwingGallery we have now completed the porting process. However, we can have
some fun by adding the option to use different look and feels. This can be done by defining
two radio buttons which will select either the basic look and feel or a motif style look and feel
and adding them to a button group. The associated RadioButtonHandler then loads into
UIManager whichever look and feel has been selected (for example,
UIManager.setLookAndFeel("java.awt.swing.motif.MotifLookAndFeel");). Essentially,
this will cause the Swing components to change their UI delegates to ones which draw, in this
case, motif style components. To ensure that all components update their display, one of the
Swing utility facilities is used (for example SwingUtilities.updateComponentTreeUI();).Thus
to change the whole displays look and feel we only need to write a few lines of Java. Note
that this process may throw an exception if an unavailable look and feel has been specified.
The specification of the SwingGallery class is presented in Listing 4.
Listing 4: The SwingGallery class
package swing.gallery;
import java.awt.Container;
import java.awt.event.*;
import java.awt.swing.*;
import java.awt.swing.border.*;
// Now need to make class a subclass of JFrame
public class SwingGallery extends JFrame {

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

Figure 5: The SwingGallery application (in basic and motif)

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

Das könnte Ihnen auch gefallen