A Java Action, ActionListener, and AbstractAction example

Java Swing FAQ: Can you provide a complete example of how to use the Java Action interface and the Java AbstractAction class?

The Java Action interface and AbstractAction class are terrific ways of encapsulating behaviors (logic), especially when an action can be triggered from more than one place in your Java/Swing application.

Here's a quick blurb on the Java Action and AbstractAction classes from the Swing Tutorial:

An Action can be used to separate functionality and state from a component. For example, if you have two or more components that perform the same function, consider using an Action object to implement the function.

An Action object is an action listener that provides not only action-event handling, but also centralized handling of the state of action-event-firing components such as tool bar buttons, menu items, common buttons, and text fields. The state that an action can handle includes text, icon, mnemonic, enabled, and selected status.

The most common way an action event can be triggered from multiple places in a Java/Swing application is through the Java menubar (JMenuBar) and toolbar (JToolBar), so in this tutorial I'll demonstrate how to create your own instances of the AbstractAction class to create easily reusable actions in your Java/Swing applications.

Creating a simple Java Action/AbstractAction

Creating a simple Java Action is very simple; just extend the AbstractAction class, add an icon if you prefer, and then implement the actionPerformed method.

Here's an implementation of an AbstractAction I named CutAction:

public class CutAction extends AbstractAction
{
  public CutAction(String name, ImageIcon icon, String shortDescription, Integer mnemonic)
  {
    super(name, icon);
    putValue(SHORT_DESCRIPTION, shortDescription);
    putValue(MNEMONIC_KEY, mnemonic);
  }

  public void actionPerformed(ActionEvent e)
  {
    JOptionPane.showMessageDialog(null, "Would have done the 'Cut' action.");
  }
}

As you can see, all it does when the actionPerformed method is called is display a dialog, but in your Java code you can implement whatever you want/need to implement.

(Note that I've named this class CutAction because in my complete class shown below I'll have a CutAction, a CopyAction, and a PasteAction.)

Create your Java Action

It's very easy to create a Java Action object. Just create an ImageIcon if you prefer, then call the constructor:

ImageIcon cutIcon = new ImageIcon(JavaAbstractActionExample.class.getResource("Cut-32.png"));
Action cutAction = new CutAction("Cut", cutIcon, "Cut stuff onto the clipboard", new Integer(KeyEvent.VK_CUT));

Using your AbstractAction in a Java menu or toolbar

Once you have an instance of an AbstractAction-based class, you can just create a JMenuItem like this:

// create the java menu item, giving it our action
JMenuItem cutMenuItem = new JMenuItem(cutAction);

You can also create a JButton and add it to a Java toolbar (JToolBar) like this:

// create the java toolbar
JToolBar toolBar = new JToolBar();

// create a java button (JButton), giving it our Action
JButton cutButton = new JButton(cutAction);

// add the button to the toolbar
toolBar.add(cutButton);

As you can see, the Java/Swing API is built to expect and use the Java Action class, and once you've defined your Action, all of this is very straightforward.

My Java AbstractAction demo class

Now that you've seen the background information, here's the source code for a complete Java class which shows several custom actions which extend the Java AbstractAction class:

package action;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class JavaAbstractActionExample extends JPanel
{
  // our actions
  Action cutAction, copyAction, pasteAction;
  
  // our icons for the actions
  ImageIcon cutIcon, copyIcon, pasteIcon;

  public JavaAbstractActionExample()
  {
    super(new BorderLayout());
    createActions();
  }

  private void createActions()
  {
    // create our icons (for the toolbar)
    cutIcon = new ImageIcon(JavaAbstractActionExample.class.getResource("Cut-32.png"));
    copyIcon = new ImageIcon(JavaAbstractActionExample.class.getResource("Copy-32.png"));
    pasteIcon = new ImageIcon(JavaAbstractActionExample.class.getResource("Paste-32.png"));

    // create our actions
    cutAction = new CutAction("Cut", cutIcon, "Cut stuff onto the clipboard", new Integer(KeyEvent.VK_CUT));
    copyAction = new CopyAction("Copy", copyIcon, "Copy stuff to the clipboard", new Integer(KeyEvent.VK_COPY));
    pasteAction = new PasteAction("Paste", pasteIcon, "Paste whatever is on the clipboard", new Integer(KeyEvent.VK_PASTE));
  }

  /**
   * Create a JMenuBar, populating it with our Actions.
   */
  private JMenuBar createMenuBar()
  {
    // create the menubar
    JMenuBar menuBar = new JMenuBar();
    
    // create our main menu
    JMenu fileMenu = new JMenu("File");
    JMenu editMenu = new JMenu("Edit");

    // create our menu items, using the same actions the toolbar buttons use
    JMenuItem cutMenuItem = new JMenuItem(cutAction);
    JMenuItem copyMenuItem = new JMenuItem(copyAction);
    JMenuItem pasteMenuItem = new JMenuItem(pasteAction);

    // add the menu items to the Edit menu
    editMenu.add(cutMenuItem);
    editMenu.add(copyMenuItem);
    editMenu.add(pasteMenuItem);

    // add the menus to the menubar
    menuBar.add(fileMenu);
    menuBar.add(editMenu);
    
    return menuBar;
  }

  /**
   * Create a JToolBar using our Actions.
   */
  private JToolBar createToolBar()
  {
    // create our toolbar
    JToolBar toolBar = new JToolBar();

    // create our toolbar buttons, using the same actions the menuitems use
    JButton cutButton = new JButton(cutAction);
    JButton copyButton = new JButton(copyAction);
    JButton pasteButton = new JButton(pasteAction);
    
    // add our buttons to the toolbar
    toolBar.add(cutButton);
    toolBar.add(copyButton);
    toolBar.add(pasteButton);
    
    return toolBar;
  }

  /**
   * Our "Cut" action.
   */
  public class CutAction extends AbstractAction
  {
    public CutAction(String name, ImageIcon icon, String shortDescription, Integer mnemonic)
    {
      super(name, icon);
      putValue(SHORT_DESCRIPTION, shortDescription);
      putValue(MNEMONIC_KEY, mnemonic);
    }

    public void actionPerformed(ActionEvent e)
    {
      JOptionPane.showMessageDialog(null, "Would have done the 'Cut' action.");
    }
  }

  /**
   * Our "Copy" action.
   */
  public class CopyAction extends AbstractAction
  {
    public CopyAction(String name, ImageIcon icon, String shortDescription, Integer mnemonic)
    {
      super(name, icon);
      putValue(SHORT_DESCRIPTION, shortDescription);
      putValue(MNEMONIC_KEY, mnemonic);
    }

    public void actionPerformed(ActionEvent e)
    {
      JOptionPane.showMessageDialog(null, "Would have done the 'Copy' action.");
    }
  }

  /**
   * Our "Paste" action.
   */
  public class PasteAction extends AbstractAction
  {
    public PasteAction(String name, ImageIcon icon, String shortDescription, Integer mnemonic)
    {
      super(name, icon);
      putValue(SHORT_DESCRIPTION, shortDescription);
      putValue(MNEMONIC_KEY, mnemonic);
    }

    public void actionPerformed(ActionEvent e)
    {
      JOptionPane.showMessageDialog(null, "Would have done the 'Paste' action.");
    }
  }

  private static void createAndShowGUI()
  {
    // create a simple jframe
    JFrame frame = new JFrame("Java AbstractAction Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // construct our panel, including our toolbar
    JavaAbstractActionExample panel = new JavaAbstractActionExample();
    panel.add(panel.createToolBar(), BorderLayout.PAGE_START);
    panel.setOpaque(true);
    frame.setContentPane(panel);

    // add the menubar to the jframe
    frame.setJMenuBar(panel.createMenuBar());
    
    // show the jframe
    frame.setPreferredSize(new Dimension(450, 300));
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

  public static void main(String[] args)
  {
    javax.swing.SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        createAndShowGUI();
      }
    });
  }
}

Sorry, none of these AbstractAction implementations are too exciting, but I'm trying to keep it simple, while still giving you some code you can work with.

Java Action and AbstractAction summary

I hope this Java Action and AbstractAction tutorial has been helpful. As you can see, it's very straightforward to implement an AbstractAction, and then use along with a JMenuBar JMenu JMenuItem JButton and JToolBar.