We mentioned before that Swing components can easily change their appearance, like master spies or thespians. Generally, different kinds of components within an application have coordinated appearances that are similar in some way. For example, they probably use the same font and the same basic color scheme. The collection of appearances and common behavior of GUI components is called a look-and-feel (L&F).
Part of the job of designing a GUI for an operating system is designing the L&F. Mac OS, therefore, has its own distinctive L&F, as does Windows. Java offers several different L&F schemes for Swing components. If you’re adept at graphic design, you can write your own L&F schemes and easily convince Swing to use them. This chameleon-like ability to change appearance is called pluggable look-and-feel, sometimes abbreviated PLAF (don’t pronounce that out loud if others are eating).
Seeing is believing. Here’s an example that creates a handful of Swing components. Menu items allow you to change the L&F dynamically while the application is running:
//file: QuickChange.java
import
java.awt.*
;
import
java.awt.event.*
;
import
javax.swing.*
;
public
class
QuickChange
extends
JFrame
{
public
QuickChange
()
{
super
(
"QuickChange v1.0"
);
createGUI
();
}
protected
void
createGUI
()
{
setSize
(
300
,
200
);
// create a simple File menu
JMenu
file
=
new
JMenu
(
"File"
,
true
);
JMenuItem
quit
=
new
JMenuItem
(
"Quit"
);
file
.
add
(
quit
);
quit
.
addActionListener
(
new
ActionListener
()
{
public
void
actionPerformed
(
ActionEvent
e
)
{
System
.
exit
(
0
);
}
});
// create the Look & Feel menu
JMenu
lnf
=
new
JMenu
(
"Look & Feel"
,
true
);
ButtonGroup
buttonGroup
=
new
ButtonGroup
();
final
UIManager
.
LookAndFeelInfo
[]
info
=
UIManager
.
getInstalledLookAndFeels
();
for
(
int
i
=
0
;
i
<
info
.
length
;
i
++)
{
JRadioButtonMenuItem
item
=
new
JRadioButtonMenuItem
(
info
[
i
].
getName
(),
i
==
0
);
final
String
className
=
info
[
i
].
getClassName
();
item
.
addActionListener
(
new
ActionListener
()
{
public
void
actionPerformed
(
ActionEvent
ae
)
{
try
{
UIManager
.
setLookAndFeel
(
className
);
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
e
);
}
SwingUtilities
.
updateComponentTreeUI
(
QuickChange
.
this
);
}
});
buttonGroup
.
add
(
item
);
lnf
.
add
(
item
);
}
// add the menu bar
JMenuBar
mb
=
new
JMenuBar
();
mb
.
add
(
file
);
mb
.
add
(
lnf
);
setJMenuBar
(
mb
);
// add some components
JPanel
jp
=
new
JPanel
();
jp
.
add
(
new
JCheckBox
(
"JCheckBox"
));
String
[]
names
=
new
String
[]
{
"Tosca"
,
"Cavaradossi"
,
"Scarpia"
,
"Angelotti"
,
"Spoletta"
,
"Sciarrone"
,
"Carceriere"
,
"Il sagrestano"
,
"Un pastore"
};
jp
.
add
(
new
JComboBox
(
names
));
jp
.
add
(
new
JButton
(
"JButton"
));
jp
.
add
(
new
JLabel
(
"JLabel"
));
jp
.
add
(
new
JTextField
(
"JTextField"
));
JPanel
main
=
new
JPanel
(
new
GridLayout
(
1
,
2
));
main
.
add
(
jp
);
main
.
add
(
new
JScrollPane
(
new
JList
(
names
)));
setContentPane
(
main
);
setDefaultCloseOperation
(
JFrame
.
EXIT_ON_CLOSE
);
}
public
static
void
main
(
String
[]
args
)
{
new
QuickChange
().
setVisible
(
true
);
}
}
The interesting part of this application is creating a menu of the
available L&Fs. First, we ask a class called UIManager
to tell us all
about the available L&Fs on our computer:
final
UIManager
.
LookAndFeelInfo
[]
info
=
UIManager
.
getInstalledLookAndFeels
();
Information about L&Fs is returned as instances of UIManager.LookAndFeelInfo
. Despite the long
name, there’s not much to this class; it just associates a name, such as
Metal, and the name of the class that
implements the L&F, such as javax
.swing.plaf.metal.MetalLookAndFeel
. In the
QuickChange
example, we create
a menu item from each L&F name. If the menu item is selected, we tell
the UIManager
to use the selected
L&F class. To make sure all the components are redrawn with the new
L&F, we call updateComponentTreeUI()
,
a static method in the SwingUtilities
class.
The JDK includes several L&Fs: Windows, OS X, Motif, the original Metal L&F, the highly customizable Synth, and the newest edition, Nimbus. Windows, OS X, and Motif are recreations of their corresponding native desktop environments. If you’re running Swing on Mac OS X, the default L&F is an implementation of Aqua, the UI design for all new Mac applications. Unfortunately, you cannot use this L&F on any other platforms because of licensing issues (the Windows L&F has similar restrictions).
The Metal L&F and its Ocean theme are the default on some platforms, but at this point they appear dated compared to modern windowing systems. The newest edition, Nimbus, is a far superior alternative. Its aethetics are on par with modern windowing systems and its use of scaleable vector graphics allows it to shine on high-density displays at various sizes. Nimbus is actually a highly evolved subclass of the Synth L&F.
Synth accommodates the new trend in skinnable user interfaces. Many applications now allow users to customize the L&F very easily, using only images and simple preferences files to create new appearances. Skinnability is not the same as a full-blown pluggable L&F, but it lets you do a lot without any programming required. Synth acts like an ordinary L&F, but can be customized through the use of images and XML description files to create new looks. For example, the borders of components (such as the shiny metal look of the Metal L&F) can be described by providing an example image and then specifying the offsets of the interior “corners” as well as the method to use (stretch or tile) to cover larger areas. Synth then uses the image to paint the borders of whatever components you specify. Synth can do quite a lot and even allows you to specify Java objects to be involved in painting, so you can resort to programming again if your L&F gets too complex.
Get Learning Java, 4th Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.