Creating Buttons in Java GUI Programming
A JButton can show an icon in addition to text, or instead of text, and icons are represented by the Icon interface.
A Button That Shows a Picture
A button in a graphical user interface does not have to show words. It can show a picture, or both a picture and words. Before reading any rules about how this works, look at the small program below and follow what it does. It draws a picture, wraps that picture so a button can use it, and attaches it to a button that also has the text Save. Pay attention to the moment the button first receives its icon, because that moment is the thread that connects the whole process.
- Lines 1 to 5 draw a small red square onto a BufferedImage
- Line 6 wraps the finished picture as an ImageIcon
- Line 7 gives the button both text and the icon through the constructor
What do you think happens?
When saveButton appears on screen, what does it show?
Reveal answer
The red square and the word Save together
The constructor was given both a text argument and an icon argument, so the button displays both. Text and icon are not mutually exclusive on a JButton.
Tracing the Icon Through the Code
The picture changes form several times on its way to the button. Follow it stage by stage and ask, at each stage, which object currently holds the picture. This is the thread that connects the whole process.
- 1Drawing stage: the pixels are placed on a BufferedImage. The picture lives in the BufferedImage, which is a grid of pixel data that the program can paint on.
- 2Wrapping stage: the BufferedImage is passed to the ImageIcon constructor. The picture is now held by an ImageIcon, which is an object that represents an icon. This is the only point where the picture is converted into an icon.
- 3Attaching stage: the ImageIcon is handed to the button, either through the constructor or through a later call to
setIcon(). The button now holds the icon and can draw it. - 4Display stage: the button draws the icon, alongside its text if it has any. If the attaching stage was skipped or applied to the wrong button, the display stage shows something different from what the code appeared to promise.
Text, Icon, or Both
A JButton has two display slots that can be filled independently: a text label and an icon. The source describes a button that can show an icon in addition to text, or instead of text. This means a button can carry only a label, only a picture, or both. The source also mentions a constructor that takes just the icon, which creates a button with an icon and no text.
- The first button has an icon and no text
- The second button has text and no icon
- The third button has both, because both arguments are supplied
The same ImageIcon object can be used to fill the icon slot in any of these forms. Choosing text, icon, or both is a decision about which slots you fill, not a different kind of button.
Three Routes to a Button
The source describes three routes by which a JButton can receive an icon. Each route places the icon at a different point in the sequence of creating the button, which is why the order of steps matters when something goes wrong.
| Route | When the icon is applied | What the code looks like |
|---|---|---|
| Constructor with text and icon | At the moment the button is created | new JButton(text, icon) |
| setIcon() on an existing button | After the button already exists | button.setIcon(icon) |
| Action with Action.SMALL_ICON | Stored on the Action, then read when a button is built from that Action | action.putValue(Action.SMALL_ICON, icon) followed by new JButton(action) |
The three routes by which an icon reaches a JButton, as described in the source
- Route 2 gives the icon to a button that already exists
- Route 3 stores the icon as the SMALL_ICON value of an Action before the button is built
From BufferedImage to ImageIcon to JButton
Icons are usually created as ImageIcons, and an ImageIcon can be built from a BufferedImage on which a custom picture has been drawn. The picture therefore moves along a path: it begins as pixel data in a BufferedImage, is converted once into an ImageIcon, and reaches the button through one of the three routes above.
The conversion happens only once, at the ImageIcon step. The BufferedImage is the place where the picture is painted, and the ImageIcon is the object the button can accept. Keeping this two-step distinction in mind makes it easier to see which object to inspect when an icon fails to appear.
Tracing Where the Icon Goes Missing
When an icon does not appear, the first useful question is which route the icon took. The point where the displayed result stops matching what you expected is usually the step where the icon was attached, or the step where it was not. The flowchart below follows a single icon through the decision of which route to use, and marks the kind of outcome that signals a departure from expectation.
- 1If you used the constructor, check that the icon was passed as the second argument.
- 2If you used
setIcon(), check that it was called on the button you are displaying. - 3If you used an action, check that
putValuewith Action.SMALL_ICON happened before the button was built.
Mistakes Beginners Make with Icons
Common mistake Expecting the icon to appear when only a BufferedImage was created
Why it failsThe picture must be wrapped as an ImageIcon and then attached to a button. A BufferedImage on its own is not an icon a button can display.
Do this insteadPass the BufferedImage to the ImageIcon constructor, then give the ImageIcon to the button.
Common mistake Calling setIcon() on a different button from the one being displayed
What it looks likeThe code sets the icon on one JButton variable while the window shows another button.
Why it failssetIcon()only affects the button it is called on, so the displayed button never receives the icon.Do this insteadConfirm that setIcon() is called on the same button object that is added to the window.
Common mistake Storing the icon on an Action after the button is built
Why it failsThe source says the Action.SMALL_ICON value should be set before the button is built from that Action. Building the button first leaves the icon out of the sequence the button was constructed from.
Do this insteadCall putValue with Action.SMALL_ICON first, then create the JButton from the Action.
Common mistake Forgetting that the constructor takes the icon as its second argument when text comes first
Practice: Finding the Departure Point
A student writes the code below, runs the program, and sees a button with the text Save but no picture. Using the three routes and the order of steps, identify the line where the displayed result departs from what was expected, and explain what change would fix it.
Hints
- Start from the last line that touches the button and work backwards.
- Ask whether the icon was ever handed to the button, and whether the handoff happened on the right object at the right time.
- Remember that
setIcon()only affects the button it is called on.
- The icon is created correctly
- The icon is attached to
helperButton, not tosaveButton
Key Takeaways
- A
JButtoncan show an icon in addition to text, or instead of text, and icons are represented by the Icon interface. - Icons are usually created as ImageIcons, and an ImageIcon can be built from a BufferedImage on which a custom picture has been drawn.
- An icon can reach a button through the constructor that takes text and icon, through
setIcon(), or through an Action whose Action.SMALL_ICON value holds the icon. - When an icon is missing, trace which route it took and check the order of the steps that attach it, since the departure from expectation is usually at the attaching step.