Concepts / Understanding Action Properties

Understanding Action Properties

An Action can be passed to the constructor of a JButton or a JMenuItem, so one Action can drive several components.

  • Programming

One Action, Two Components

Suppose a window needs a button and a menu item that do the same job. The button sits where the user can click it directly, and the menu item sits inside a menu. You could write separate code for each, but then every change would have to be made twice. Swing offers a shorter route: an Action object. An Action can be passed to the constructor of a JButton or a JMenuItem, so one Action can drive several components.

This article follows one small program from start to finish. You will watch which object is passed where, what changes when the Action is disabled, and what changes when it is renamed. You do not need to run the program yourself to follow the discussion.

Tracing the Shared Action

java
Notes on the code
  • The anonymous AbstractAction is a stand-in for the Action definition the source refers to as clearAction; the variable name and the message text are the parts to focus on.
  • The same clearAction object is passed to the JButton constructor and to the JMenuItem constructor.
  • The final line changes the enabled state of the Action only. Neither component is named in that line.

Read the program once and focus on which object is passed where. There is one Action object, created on the line that declares clearAction. That same object is handed to the button and then to the menu item. Neither constructor copies the Action; each component is built from it. The program then calls setEnabled(false) on clearAction. Notice that this line never mentions button or item.

clearActionAction objectJButtonbuttonJMenuItemmenu entrybuilt frombuilt from
Both the JButton and the JMenuItem are built from the same clearAction object, so both connect to that single Action.

What the Action Holds

An Action is not just a method that runs when something is clicked. It also carries properties that describe how it should appear and whether it is available. The source names two of them directly: the NAME property, which supplies the text shown by components built from the Action, and the enabled state, which determines whether those components can be used. Because these properties live on the Action, the Action is the single place where they are stored.

This arrangement is what makes one Action useful for several components. The button and the menu item do not each hold their own copy of the name or the enabled state. They read those values from the shared Action. When the Action changes, every component built from it reflects the change.

Predicting the Effect of Disabling

What do you think happens?

After clearAction.setEnabled(false) runs, what happens to the button and the menu item?

  • Only the button is disabled

  • Only the menu item is disabled

  • Both are disabled

  • Neither one changes

Reveal answer
Answer:

Both are disabled.

The enabled state belongs to the Action, and both components are built from that same Action. Changing the Action changes every component built from it. The line of code never names either component.

Trace the program's state step by step. Before the setEnabled call, the Action is enabled, so the button and the menu item are both available. After the call, the Action is disabled. Nothing else in the program was edited. The effect reached both components because each one reads its state from the shared Action.

Renaming the Action

Renaming works the same way as disabling. The NAME property belongs to the Action, so changing it updates the text of every component built from that Action. In the code below, the Action's NAME is changed from Clear to Reset. The surrounding program is unchanged; only the rename line differs.

Before
clearAction.putValue(Action.NAME, "Clear");

The button and the menu item both show the text Clear.

After
clearAction.putValue(Action.NAME, "Reset");

The button and the menu item both show the text Reset.

Button text: ClearButton text: ResetMenu item text: ClearMenu item text: Reset
Before the rename, the button and the menu item both display Clear. After the NAME property changes on the Action, both display Reset.

Why You Can Drop the Component Variables

In the program above, the button and the menu item are stored in local variables named button and item. Once they have been created and added to their containers, a learner may stop keeping those variables. The source states that any later change you want to make, such as enabling, disabling, or renaming, can be done on the Action object alone. You do not need a variable that points to the button in order to disable it, because the disable request goes to the Action.

Mistakes When Managing Shared Actions

  • Common mistake

    Trying to disable the button and the menu item separately after both were built from the same Action

    Why it fails

    The enabled state belongs to the Action. Changing it on the Action already updates every component built from it.

    Do this instead

    Call setEnabled on the shared Action once, and both components will reflect the change.

  • Common mistake

    Expecting a rename to change only the button

    Why it fails

    The NAME property belongs to the Action, so changing it updates the text of every component built from that Action, including the menu item.

    Do this instead

    Change the NAME on the Action with putValue(Action.NAME, ...) and check both components.

  • Common mistake

    Assuming the variables for the components must always be kept

    Why it fails

    Later changes to enabled state or name can be made on the Action alone, so the component variables are not needed for those changes.

    Do this instead

    Keep the Action in a variable you can reach, and keep component variables only when the program needs them for another purpose.

Applying the Shared Action

EASY

A program creates an Action named saveAction and passes it to both a JButton and a JMenuItem. Write the single line that changes the text shown by both components from Save to Save As, and state which components change without any other edits.

Hints
  • The text shown by the components is held in the NAME property of the Action.
  • Use putValue with Action.NAME on saveAction, not on the button or the menu item.
  • Both components are built from saveAction, so both should show the new text.

Key Takeaways

  • An Action can be passed to the constructor of a JButton or a JMenuItem, so one Action can drive several components.
  • Enabling, disabling, and renaming an Action update every component built from it, because those properties belong to the Action.
  • Changing the enabled state or the NAME property is done on the Action object, not on each component.
  • Once the components are created, a learner does not need to keep variables that point to them to make those later changes.