Subpages: 1. Labels and buttons overview
2. Custom buttons: part I - Transparent buttons
3. Custom buttons: part II - Polygonal buttons
4. Custom buttons: part III - Tooltip management
Chapter 5. Labels and Buttons
In this chapter:
- Labels and buttons overview
- Custom buttons: part I - Transparent buttons
- Custom buttons: part II - Polygonal buttons
- Custom buttons: part III - Tooltip management
5.1 Labels and buttons overview
5.1.1 JLabel
class javax.swing.JLabel
JLabel is one of the simplest Swing components, and is most often used to identify other components. JLabel can display text, an icon, or both in any combination of positions (note that text will always overlap the icon). The following code creates four different JLabels and places them in a GridLayout, and figure 5.1 illustrates.

Figure 5.1 JLabel demo
<<file figure5-1.gif>>
The Code: LabelDemo.java
see \Chapter5\6
import java.awt.*;
import javax.swing.*;
class LabelDemo extends JFrame
{
public LabelDemo() {
super("JLabel Demo");
setSize(600, 100);
JPanel content = (JPanel) getContentPane();
content.setLayout(new GridLayout(1, 4, 4, 4));
JLabel label = new JLabel();
label.setText("JLabel");
label.setBackground(Color.white);
content.add(label);
label = new JLabel("JLabel",
SwingConstants.CENTER);
label.setOpaque(true);
label.setBackground(Color.white);
content.add(label);
label = new JLabel("JLabel");
label.setFont(new Font("Helvetica", Font.BOLD, 18));
label.setOpaque(true);
label.setBackground(Color.white);
content.add(label);
ImageIcon image = new ImageIcon("flight.gif");
label = new JLabel("JLabel", image,
SwingConstants.RIGHT);
label.setVerticalTextPosition(SwingConstants.TOP);
label.setOpaque(true);
label.setBackground(Color.white);
content.add(label);
setVisible(true);
}
public static void main(String args[]) {
new LabelDemo();
}
}
The first label is created with the default constructor and its text is set using the setText() method. We then set its background to white, but when we run this program the background of this label shows up as light gray! The reason this happens is because we didn't force this label to be opaque. In chapter 2 we learned that Swing components support transparency, which means that a component does not have to paint every pixel within its bounds. So when a component is not opaque it will not fill its background, and a JLabel (as with most components) is non-opaque by default.
Also note that we can set the font and foreground color of a JLabel using JComponent's setFont() and setForeground() methods. Refer back to chapter 2 for information about working the the Font and Color classes.
The default horizontal alignment of JLabel is LEFT if only text is used, and CENTER if an image or an image and text are used. An image will appear to the left of the text by default, and every JLabel is initialized with a centered vertical alignment. Each of these default behaviors can easily be adjusted as we will see below.
5.1.2 Text Alignment
To specify alignment or position in many Swing components we make us of the javax.swing.SwingConstants interface. This defines several constant strings, five of which are applicable to JLabel's text alignment settings:
SwingConstants.LEFT
SwingConstants.CENTER
SwingConstants.RIGHT
SwingConstants.TOP
SwingConstants.BOTTOM
Alignment of both a label's text and icon can be specified in the constructor or through the use of setHorizontalAlignment() and setVerticalAlignment() methods. The text can be aligned both vertically or horizontally, independent of the icon (text will overlap the icon when necessary) using the setHorizontalTextAlignment() and setVerticalTextAlignment() methods. Figure 5.2 shows where a JLabel's text will be placed corresponding to each possible combination of vertical and horizontal text alignment settings.

Figure 5.2 JLabel text alignment
<<file figure5-2.gif>>
5.1.3 Icons and Icon Alignment
The simple example above included a label with an image of an airplane by reading a GIF file in as an ImageIcon and passing it to a JLabel constructor:
ImageIcon image = new ImageIcon("flight.gif");
label = new JLabel("JLabel", image,
SwingConstants.RIGHT);
An image can also be set or replaced at any time using the setIcon() method (passing null will remove the current icon, if any). JLabel also supports a disabled icon for use when a label is in the disabled state. To assign a disabled icon we use the setDisabledIcon() method.
Note: Animated GIFs can be used with ImageIcon's and labels just as any static GIF, and require no additional code. ImageIcon also supports JPGs.
5.1.4 GrayFilter
class javax.swing.GrayFilter
The GrayFilter class can be used to create disabled images using its static createDisabledImage() method:
ImageIcon disabledImage = new ImageIcon(
GrayFilter.createDisabledImage(image.getImage()));
Figure 5.3 shows the fourth label in LabelDemo now using a disabled icon generated by GrayFilter. Note that JLabel only displays the disabled icon when it has been disabled using JComponent's setEnabled() method.

Figure 5.3 Demonstrating a disabled icon using GrayFilter
<<file figure5-3.gif>>
5.1.5 The labelFor and the displayedMnemonic properties
JLabel maintains a labelFor property and a displayedMnemonic property. The displayed mnemonic is a character that, when pressed in syncronization with ALT (e.g. ALT+R), will call JComponent's requestFocus() method on the component referenced by the labelFor property. The first instance of displayed mnemonic character (if any) in a label's text will be underlined. We can access these properties using typical get/set accessors (see API docs).
5.1.6 AbstractButton
abstract class javax.swing.AbstractButton
AbstractButton is the template class from which all buttons are defined. This includes push buttons, toggle buttons, check boxes, radio buttons, menu items, and menus themselves. Its direct subclasses are JButton, JToggleButton, and JMenuItem. There are no subclasses of JButton in Swing. JToggleButton has two subclasses: JCheckBox, JRadioButton. JMenuItem has three subclasses: JCheckBoxMenuItem, JRadioButtonMenuItem, and JMenu. The remainder of this chapter will focus on JButton and the JToggleButton family. (See chapter 12 for more about menus and menu items).
5.1.7 The ButtonModel interface
abstract interface javax.swing.ButtonModel
Each button class uses a model to store its state. We can access any button's model with the AbstractButton getModel() and setModel() methods. The ButtonModel interface is the template interface from which all button models are defined. JButton uses the DefaultButtonModel implementation. JToggleButton defines an inner class extension of DefaultButtonModel, JToggleButton.ToggleButtonModel, which is used by itself, as well as both its subclasses.
The following boolean property values represent the state of a button, and have associated isXX() and setXX() accessors in DefaultButtonModel:
selected: Switches state on each click (only relevant for JToggleButtons).
pressed: True when the button is held down with the mouse.
rollover: True when the mouse is hovering over the button.
armed: This state stops events from being fired when we press a button with the mouse, and then release the mouse when its cursor is outside that button's bounds.
enabled: True when the button is active. None of the other properties can normally be changed when this is false.
A button's keyboard mnemonic is also stored in its model, as well as the ButtonGroup it belongs to, if any. (We'll discuss the ButtonGroup class while we discuss JToggleButtons, as it only applies to this family of buttons.)
5.1.8 JButton
class javax.swing.JButton
JButton is a basic push-button, one of the simplest Swing components. Almost everything we know about JLabel also applies to JButton. We can add images, specify text and image alignment, set foreground and background colors (remember to call setOpaque(true)), set fonts, etc. Additionally, we can add ActionListeners, ChangeListeners, and ItemListeners to receive ActionEvents, ChangeEvents, and ItemEvents respectively when any properties in its model change value. We will see how to build a custom, non-rectangular subclass of JButton in the chapter examples.
In most application dialogs we expect to find a button which initially has the focus and will capture an Enter key press, regardless of the current keyboard focus (unless focus is within a multi-line text component). This is referred to as the default button. Any JRootPane container can define a default button using JRootPane's setDefaultButton() method (passing null will disable this feature). For instance, to make a button the default button for a JFrame we would do the following:
myJFrame.getRootPane().setDefaultButton(myButton);
The isDefaultButton() method returns a boolean value indicating whether or not the button instance it was called on is a default button for a JRootPane.
We most often register an ActionListener with a button to receive ActionEvents from that button whenever it is clicked (Note that if a button has the focus, pressing the space-bar will also fire an ActionEvent). ActionEvents carry with them information about the event that occurred including, most importantly, which component they came from. (Note that an ActionListener can be registered to receive events from any number of components. See chapter 2 for an overview of event handling.)
To create an ActionListener we need to create a class that implements the ActionListener interface, which requires the definition of its actionPerformed() method. Once we have built an ActionListener we can register it with a button using the JComponent's addActionListener() method. The following is a typical inner class implementation. When an ActionEvent is intercepted, "Swing is powerful!!" is printed to standard output.
JButton myButton = new JButton();
ActionListener act = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Swing is powerful!!");
}
};
myButton.addActionListener(act);
We primarily use this method throughout this book to attach listeners to components. However, some developers prefer to implement the ActionListener interface in the class that owns the button instance. In the case of classes with several registered components, this is not as efficient as using a separate listener class and can require writing common code in several places. Specifically, implementing ActionListener for use with multiple event sources requires us to check the source of each ActionEvent (using ActionEvent's getSource() method) before processing.
An icon can be assigned to a JButton instance via the constructor or with the setIcon() method. We can optionally assign individual icons for the normal, selected, pressed, rollover, and disabled states. See the API docs for more detail on the following methods:
setDisabledSelectedIcon()
setPressedIcon()
setRolloverIcon()
setRolloverSelectedIcon()
setSelectedIcon()
A button can also be disabled and enabled the same way as a JLabel, using setEnabled(). As we would expect, a disabled button will not respond to any user actions.
A button's keyboard mnemonic provides an alternative way of activation. To add a keyboard mnemonic to a button we use the setMnemonic() method:
button.setMnemonic('R');
We can then activate a button (equivalent to clicking it) by pressing ALT and its mnemonic key simultaneously. (e.g. ALT+R) The first appearance of the assigned mnemonic character, if any, in the button text will be underlined to indicate which key activates it. There is no distinction made between upper and lower case characters. Avoid duplicating mnemonics for components sharing a common ancestor.
5.1.9 JToggleButton
class javax.swing.JToggleButton
JToggleButton provides a selected state mechanism which extends to its children, JCheckBox and JRadioButton, and corresponds to the selected property we discussed in section 5.2. We can test whether a toggle button is selected using AbstractButton's isSelected() method, and we can set this property with its setSelected() method.
5.1.10 ButtonGroup
class javax.swing.ButtonGroup
JToggleButtons are often used in ButtonGroups. A ButtonGroup manages a set of buttons by guaranteeing that only one button within that group can be selected at any given time. Thus, only JToggleButton and its subclasses are useful in a ButtonGroup (because a JButton does not maintain a selected state). The following code constructs three JToggleButtons and places them in a single ButtonGroup.

Figure 5.4 JToggleButtons in a ButtonGroup
<<file figure5-4.gif>>
The Code: ToggleButtonDemo.java
see \Chapter5\6
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class ToggleButtonDemo extends JFrame
{
public ToggleButtonDemo () {
super("ToggleButton/ButtonGroup Demo");
getContentPane().setLayout(new FlowLayout());
JToggleButton button1 = new JToggleButton("Button 1",true);
getContentPane().add(button1);
JToggleButton button2 = new JToggleButton("Button 2",false);
getContentPane().add(button2);
JToggleButton button3 = new JToggleButton("Button 3",false);
getContentPane().add(button3);
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(button1);
buttonGroup.add(button2);
buttonGroup.add(button3);
pack();
setVisible(true);
}
public static void main(String args[]) {
new ToggleButtonDemo();
}
}
5.1.11 JCheckBox and JRadioButton
class javax.swing.JCheckBox, class javax.swing.JRadioButton
JCheckBox and JRadioButton both inherit all JToggleButton functionality. In fact the only significant differences between all three components is their UI delegate views (i.e. how they are rendered). Both button types are normally used to select the mode of a particular application function. Figures 5.5 and 5.6 show the previous example running with JCheckBoxes and JRadioButtons as replacements for the JToggleButtons.
![]()
Figure 5.5 JCheckBoxes in a ButtonGroup
<<file figure5-5.gif>>
![]()
Figure 5.6 JRadioButtons in a ButtonGroup
<<file figure5-6.gif>>
5.1.12 JToolTip & ToolTipManager
class javax.swing.JToolTip, class javax.swing.ToolTipManager
A JToolTip is a small popup window designed to contain informative text about a component when the mouse moves over it. We don't generally create instances of these components ourselves. Rather, we call setToolTipText() on any JComponent subclass and pass it a descriptive String. This String is then stored as a client property within that component's client properties Hashtable, and that component is then registered with the ToolTipManager (using ToolTipManager's registerComponent() method). The ToolTipManager adds a MouseListener to each component that registers with it.
To unregister a component we can pass null to that component's setToolTipText() method. This invokes ToolTipManager's unregisterComponent() method which removes its MouseListener from that component. Figure 5.7 shows a JToggleButton with simple tooltip text.
![]()
Figure 5.7 JToggleButton with tooltip text
<<file figure5-7.gif>>
The ToolTipManager is a service class that maintains a shared instance registered with AppContext (see chapter 2). We can access the ToolTipManager directly by calling its static sharedInstance() method:
ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
Internally this class uses three non-repeating Timers with delay times defaulting to 750, 500, and 4000. ToolTipManager uses these Timer's in coordination with mouse listeners to determine if and when to display a JToolTip with a component's specified tooltip text. When the mouse enters a components bounds ToolTipManager will detect this and wait 750ms until displaying a JToolTip for that component. This is referred to as the initial delay time. A JToolTip will stay visible for 4000ms or until we move the mouse outside of that component's bounds, whichever comes first. This is referred to as the dismiss delay time. The 500ms Timer represents the reshow delay time which specifies how soon the JToolTip we have just seen will appear again when this component is re-entered. Each of these delay times can be set using ToolTipManager's setDismissDelay(), setInitialDelay(), and setReshowDelay() methods.
ToolTipManager is a very nice service to have implemented for us, but it does have significant limitations. When we construct our polygonal buttons in section 5.6 below, we will find that it is not robust enough to support non-rectangular components. It is also the case that JToolTips are only designed to allow a single line of text.
5.1.13 Labels and buttons with HTML text
The Swing 1.1.1 Beta 1 release (February 1999) offers a particularly interesting new feature (among several bug fixes). Now we can use HTML text in JButton and JLabel components (as well as for tooltip text). We don't have to learn any new methods to use this functionality, and the UI delegate handles the HTML rendering for us. If a button/label's text starts with <HTML>, Swing knows to lightweight render the text in HTML format. We can use normal paragraph tags (<P>, </P>), line break tags (<BR>), etc. For instance, we can assign a multiple-line tooltip to any component like so:
myComponent.setToolTipText("<html>Multi-line tooltips<br>" +
"are easy!");
The <br> tag specifies a line break. The following example demonstrates this functionality.

Figure 5.12 A JButton and JLabel with HTML text.
<<file figure5-12.gif>>
The Code: HtmlButtons.java
see \Chapter5\3
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class HtmlButtons extends JFrame
{
public HtmlButtons() {
super("HTML Buttons and Labels");
setSize(400, 300);
getContentPane().setLayout(new FlowLayout());
String htmlText =
"<html><p><font color=\"#800080\" "+
"size=\"4\" face=\"Verdana\">JButton</font> </p>"+
"<address><font size=\"2\"><em>"+
"with HTML text</em></font>"+
"</address>";
JButton btn = new JButton(htmlText);
getContentPane().add(btn);
htmlText =
"<html><p><font color=\"#800080\" "+
"size=\"4\" face=\"Verdana\">JLabel</font> </p>"+
"<address><font size=\"2\"><em>"+
"with HTML text</em></font>"+
"</address>";
JLabel lbl = new JLabel(htmlText);
getContentPane().add(lbl);
WindowListener wndCloser = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}
public static void main(String args[]) {
new HtmlButtons();
}
}


RSS feed Java FAQ News