Concepts / Working with JCheckBox and JRadioButton Components

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.

  • Programming

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?

  • Inside a check symbol the component draws on demand

  • In an icon the component chooses for the selected state

  • In a color setting that tints the box

Reveal answer
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.

Unselectedunselected icon shownSelectedselected icon shownuser clicksuser clicks again
When the user clicks a checkbox, which icon is displayed before the click, and which replaces it after?

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.

Constructor argumentunselected iconsetIcon()unselected iconsetSelectedIcon()selected iconeither can set the unselected iconcontrols the other state
Which method or constructor argument supplies the icon for the unselected state, and which supplies it for the selected state?

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.

Worked example

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?

  1. 1
    Step 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.

  2. 2
    Step 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.

  3. 3
    Step 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.

  4. 4
    Step 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.

Result

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().

Initial unselectedcheck mark drawn, circleintendedAfter clickcircle drawn, check markintendedAfter second clickcheck mark drawn, circleintendedclick selectsclick deselects
Starting from the initial state, what icon is drawn after each action, and at which step does the rendered icon stop matching the one the code intended?

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.

ComponentUnselected icon set bySelected icon set by
JCheckBoxConstructor or setIcon()setSelectedIcon()
JRadioButtonConstructor or setIcon()setSelectedIcon()
JCheckBoxMenuItemConstructor or setIcon()setSelectedIcon()
JRadioButtonMenuItemConstructor 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 like

    A checkbox shows the wrong picture in its unselected state and the developer edits the click handler.

    Why it fails

    The unselected icon is set by the constructor or setIcon(), not by the click. The first wrong picture appears before any click happens.

    Do this instead

    Identify 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 like

    The circle image is passed to setSelectedIcon() when the design calls for it to be the unselected icon.

    Why it fails

    setIcon() controls the unselected icon and setSelectedIcon() controls the selected icon, so each state displays the wrong picture.

    Do this instead

    Map 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 like

    A developer calls setIcon() expecting it to change every checkbox in the window.

    Why it fails

    Both methods belong to the JCheckBox object, so each call affects only the particular checkbox it is called on.

    Do this instead

    Call 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

MEDIUM

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 JCheckBox draws 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 by setSelectedIcon(), with both methods called on the specific component.
  • JRadioButton, JCheckBoxMenuItem, and JRadioButtonMenuItem follow 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.