Working with JCheckBox and JRadioButton Components
A JCheckBox draws its box from a pair of Icons: one for the unselected state and one for the selected state.
A Checkbox That Looks Wrong
Imagine a Swing window with a row of checkboxes, where one of them looks wrong. It is still a box with a check mark, but the picture does not match the design you wanted. Before you can fix that, you need to know what the box on the screen actually is and which part of your program controls it.
This article starts from that practical question. You will first think about what a checkbox displays in each of its states, then trace the mechanism that produces the picture, and finally learn how to find the exact step where a customized button stops showing what you intended.
What do you think happens?
Before reading the mechanism, predict: when a JCheckBox is checked, where would you expect its checked appearance to be defined?
Reveal answer
In an icon the component chooses for the selected state
The checkmark state is not produced by drawing a check symbol on demand. The component chooses between two icons, and the choice depends only on the selection state.
Two Icons Instead of a Drawn Check Mark
A JCheckBox draws its box from a pair of Icons: one for the unselected state and one for the selected state. The component does not decide how to render a check mark each time it is painted. It looks at whether it is selected and displays the icon that belongs to that state.
Because the choice depends only on the selection state, customizing the appearance means replacing one or both of those icons. The source describes this directly: you can change the look of the check box by substituting different icons for the standard ones.
Read the diagram as a two-state cycle. Each click moves the checkbox from one state to the other, and the icon drawn follows the state. The box is never drawn from scratch as a check mark; it is always one of the two icons assigned to it.
Which Method Controls Which Icon
The two icons play different roles, and the source names the methods that control each one. The icon for the unselected state is the main icon of the JCheckBox. You can supply it when the component is constructed, or you can replace it later with setIcon().
The icon for the selected state is changed with setSelectedIcon(). Both methods belong to the JCheckBox object, so you call them on the particular checkbox you want to customize. Changing one checkbox does not require changing the others.
A simple way to hold this mapping in mind is to ask two separate questions. Which icon does this state use? If the answer is unselected, the constructor argument or setIcon() set it. If the answer is selected, setSelectedIcon() set it.
Tracing a Swapped Pair of Icons
The following scenario is an original illustration built from the rules above. Suppose a developer wants a checkbox that shows an empty circle when unselected and a check mark when selected. The developer calls setIcon() with the check mark image and setSelectedIcon() with the circle image, so the two assignments are swapped.
Finding the first wrong picture
The checkbox is meant to show a circle when unselected and a check mark when selected. Which step first produces a picture that does not match the design?
- 1Step 1: Identify the starting state
The checkbox begins unselected. The unselected icon is the one set by
setIcon(), which in this scenario was given the check mark image. - 2Step 2: Compare the displayed icon with the intended icon
The intended unselected icon is the circle. The check mark is drawn instead. The first wrong picture already appears at step 1, before any click.
- 3Step 3: Click the checkbox
The state becomes selected. The selected icon is the one set by
setSelectedIcon(), which was given the circle image. The circle is drawn, which is the opposite of the intended design. - 4Step 4: Locate the cause
The problem is not in the drawing or the click handling. It is in the two calls that set the icons. Each call must be checked against the state it controls.
The first wrong picture is the check mark shown while unselected, produced by the setIcon() call. The fix is to swap the two arguments so the circle goes to setIcon() and the check mark goes to setSelectedIcon().
The trace shows that every state is wrong, not only the selected one. The departure begins at the first step, because the unselected icon was assigned incorrectly. Tracing from the start, one step at a time, is what makes this visible. Checking only the final look of a clicked checkbox would suggest that the click logic is at fault, which is the wrong place to look.
Radio Buttons and Menu Items Follow the Same Pattern
The same pattern is not limited to checkboxes. The source states that all of this applies equally to JRadioButton, JCheckBoxMenuItem, and JRadioButtonMenuItem. A radio button therefore has an unselected icon and a selected icon, and you customize them with the same two methods: setIcon() for the unselected appearance and setSelectedIcon() for the selected appearance.
| Component | Unselected icon set by | Selected icon set by |
|---|---|---|
| JCheckBox | Constructor or setIcon() | setSelectedIcon() |
| JRadioButton | Constructor or setIcon() | setSelectedIcon() |
| JCheckBoxMenuItem | Constructor or setIcon() | setSelectedIcon() |
| JRadioButtonMenuItem | Constructor or setIcon() | setSelectedIcon() |
The two-icon customization pattern shared by the four components named in the source.
The source names the radio button as the one place where its concrete example adds a further detail. Because a radio button usually belongs to a group, its customization happens during setup alongside its grouping, as the next example shows.
Customized Radio Buttons in ToolBarDemo
The source points to ToolBarDemo.java as a concrete case. That program creates a set of radio buttons that use custom icons. It builds each button in a helper method whose documentation says it creates a JRadioButton and adds it to a specified button group.
The excerpt shows that the button group is part of the construction. Customizing a radio button therefore happens while the button is being set up, alongside its grouping. When you trace a problem in such a button, start at this setup code, because that is where its icon calls and its group membership are established together.
Mistakes When Customizing Icons
Common mistake Assuming the click logic is wrong when the box looks incorrect
What it looks likeA checkbox shows the wrong picture in its unselected state and the developer edits the click handler.
Why it failsThe unselected icon is set by the constructor or
setIcon(), not by the click. The first wrong picture appears before any click happens.Do this insteadIdentify the state where the wrong appearance first occurs, then check the call that sets the icon for that state.
Common mistake Swapping the roles of setIcon() and setSelectedIcon()
What it looks likeThe circle image is passed to setSelectedIcon() when the design calls for it to be the unselected icon.
Why it failssetIcon()controls the unselected icon andsetSelectedIcon()controls the selected icon, so each state displays the wrong picture.Do this insteadMap each argument to its state before writing the call, and verify the mapping against the design.
Common mistake Forgetting that the setters belong to a specific component
What it looks likeA developer calls setIcon() expecting it to change every checkbox in the window.
Why it failsBoth methods belong to the
JCheckBoxobject, so each call affects only the particular checkbox it is called on.Do this insteadCall the setters on each checkbox you want to customize, or use a consistent setup routine for them.
Common mistake Believing that only JCheckBox supports this two-icon customization
Locating the First Wrong Picture
A JRadioButton is meant to show a square when unselected and a filled dot when selected. Its setup calls setIcon() with the filled dot image and setSelectedIcon() with the square image. Trace the button from its creation through one click and one more click. At which step does the displayed icon first stop matching the design, and which call should be corrected?
Hints
- Start by writing down the state the button is in at creation and which icon the source assigns to that state.
- Compare each displayed icon with the intended icon before moving to the next step.
- The first mismatch tells you which setter call to inspect.
Key Takeaways
- A
JCheckBoxdraws its box from a pair of icons, one for the unselected state and one for the selected state, and it chooses between them based on its selection state. - The unselected icon is supplied by the constructor or
setIcon(), and the selected icon is supplied bysetSelectedIcon(), with both methods called on the specific component. JRadioButton,JCheckBoxMenuItem, andJRadioButtonMenuItemfollow the same two-icon pattern, so the same two methods customize them.- To debug a customized button, identify the state where the wrong appearance first occurs and check the call that sets the icon for that state.