April 24, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Understanding Action Objects in Java, Page 4

  • May 29, 2002
  • By Richard G. Baldwin, Richard G. Baldwin
  • Send Email »
  • More Articles »

getKeys method

Returns an array of Object references which are the keys for which values have been set.  Returns null if no keys have their values set.  Can be used in an action-aware component to identify and get the values for keyed properties.

getPropertyChangeListeners()

Returns an array of all the PropertyChangeListeners added to this AbstractAction object with addPropertyChangeListener().  The array is empty if no listeners have been added.  Can be used in a subclass to get a list of listeners.

Now for some code

As is my practice, I will discuss the program named ActionObj02 in fragments.  A complete listing of the program is shown in Listing 22 near the end of the lesson.  The first fragment, shown in Listing 1, simply uses the main method to instantiate an object of the GUI class.  I will discuss the definition of the GUI class later.
 

public class ActionObj02{
  public static void main(
                        String[] args){
    new GUI();
  }//end main
}//end ActionObj02

Listing 1

The MyAction class

Listing 2 shows the entire class definition for the MyAction class from which Action objects will be instantiated.
 

class MyAction extends AbstractAction{
  public void actionPerformed(
                        ActionEvent e){
    System.out.println("Action: " + 
       ((AbstractButton)e.getSource()).
                   getActionCommand());
  }//end actionPerformed
}//end class MyAction

Listing 2

Note that the MyAction class doesn't implement the Action interface directly.  Rather, it extends the AbstractAction class and implements the Action interface through inheritance.  This causes it to inherit the default behavior of the methods defined in the AbstractAction class and discussed earlier in this lesson.

Overrides actionPerformed

The MyAction class overrides the actionPerformed method.  The overridden behavior of the method is to get and display the action command for any source object (on which it is registered) that fires an ActionEvent.  By default, the action command is simply the text that is visible on the face of the source object. Thus, clicking any of the six components located on the JMenu, the JToolBar, or the JPanel (see Figure 4) will cause the text on the face of that component to be displayed.

The GUI class

Listing 3 shows the beginning of the GUI class.
 

class GUI extends JFrame{
  JMenuBar menuBar = new JMenuBar();
  JMenu menu = new JMenu("Menu");
  JToolBar toolBar = new JToolBar();
  JPanel panel = new JPanel();

Listing 3

The code in Listing 3 creates the following container objects, which are visible in Figure 4:

  • JMenu
  • JToolBar
  • JPanel
Two Action objects

Listing 4 creates two Action objects (instances of the MyAction class discussed above).  These two Action objects will be registered on various action-aware components later.
 

  Action actionObj01 = new MyAction();
  Action actionObj02 = new MyAction();

Listing 4

Control

Listing 5 creates the four check boxes and a control panel shown in the center of Figure 3.
 

  JCheckBox ckBox01 = new JCheckBox(
                          "Disable01");
  JCheckBox ckBox02 = new JCheckBox(
                          "Disable02");
  JCheckBox ckBox03 = new JCheckBox(
                      "Toggle Icon01");
  JCheckBox ckBox04 = new JCheckBox(
                      "Toggle Icon02");
  JPanel controlPanel = new JPanel();

Listing 5

The four check boxes will be used to manipulate the behavior of the two Action objects, and hence the behavior of the six associated action-aware components.  Note that the text shown on the face of the checkboxes will be modified when those checkboxes are checked and cleared.

The GUI constructor

Listing 6 shows the beginning of the constructor for the GUI class.
 

  GUI(){//constructor
    menuBar.add(menu);

    menuBar.setBorder(
               new BevelBorder(
                  BevelBorder.RAISED));

    setJMenuBar(menuBar);

Listing 6

The code in Listing 6 adds the JMenu object to the JMenuBar object, which is the standard way to construct a menu in Java.

Then it invokes the setBorder method on the menu bar to cause its edges to become visible.  I did this to make it easy to visually separate the menu bar from the tool bar that appears immediately below it in Figure 3.  (You can learn more about Swing borders at Baldwin's Java Programming Tutorials.)

Set the JMenuBar

Finally, the code in Listing 6 adds the menu bar to the JFrame.  Note, however, that this is accomplished by invoking the setJMenuBar method on the JFrame object instead of invoking an add method, (which is the way that other components are normally added to a JFrame container.)

A decorated JToolBarcontainer

Listing 7 decorates the JToolBar object with raised bevel borders, and places it in the NORTH position of the JFrame object.  This causes the toolbar to appear immediately below the menu bar in Figure 3.
 

    toolBar.setBorder(new BevelBorder(
                  BevelBorder.RAISED));
    getContentPane().add(
           toolBar,BorderLayout.NORTH);

Listing 7

(If need be, you can also learn more about the BorderLayout manager and the getContentPane method at Baldwin's Java Programming Tutorials.)

A decorated JPanel container

Listing 8 decorates the JPanel object with raised bevel borders, and places it in the SOUTH position of the JFrame object.  This causes it to appear at the bottom of the JFrame in Figure 3.
 

    panel.setBorder(new BevelBorder(
                  BevelBorder.RAISED));
    getContentPane().add(
             panel,BorderLayout.SOUTH);

Listing 8

Setting keyed values

Except for the definition of the MyAction class discussed earlier, very little of the code discussed so far has been specific to the Action interface.  However, the code in Listing 9 is very specific to the Action interface.
 

    actionObj01.putValue(
            Action.NAME,"actionObj01");

Listing 9

Listing 9 invokes the putValue method on one of the Action objects to set the value for one of the keyed properties.  As mentioned earlier, each Action object has a container for keyed properties that behaves much as a hashtable behaves.  Values are stored against keys, and can be accessed later by specifying the key.

Values are stored in that container by invoking the putValue method and passing a key and a value as parameters.  In this case, one of the constants (final variables) defined in the Action interface is used as the key.  The literal String object "actionObj01" is passed as the value.

(Note that as discussed earlier, the constant is referred to symbolically as Action.NAME, and no explicit use is made of the actual String value encapsulated in that constant.)
The remaining keyed properties

Listing 10 sets the values for each of the remaining keyed properties.
 

    actionObj01.putValue(
       Action.SMALL_ICON,new ImageIcon(
                       "redball.gif"));
    actionObj01.putValue(
            Action.SHORT_DESCRIPTION,
            "ToolTip for actionObj01");
 
    actionObj02.putValue(
            Action.NAME,"actionObj02");
    actionObj02.putValue(
       Action.SMALL_ICON,new ImageIcon(
                         "bulb2.gif"));
    actionObj02.putValue(
            Action.SHORT_DESCRIPTION,
            "ToolTip for actionObj02");

Listing 10

As mentioned earlier, these keyed properties behave as bound properties, meaning that registered objects are notified when their values change.  Checking and clearing two of the checkboxes in this program causes the values of the SMALL_ICON properties to change, thus causing the icons displayed on the components registered on the respective Action objects to change accordingly.

Build the menu

Code that I discussed earlier created a menu bar and placed a menu on that bar.  Now the time has come to place some menu items on that menu.  This process begins in Listing 11.
 

    JMenuItem mnuA1 = new JMenuItem();
    mnuA1.setAction(actionObj01);
    menu.add(mnuA1);

Listing 11

Invoke the setAction method

The code in Listing 11 is very significant relative to the use of Action objects.  Listing 11 instantiates a new JMenuItem object and then invokes the setAction method on that object, passing a reference to one of the Action objects as a parameter.

As discussed earlier, this causes the Action object to be registered as an action listener on the JMenuItem object.

PropertyChange listener registration

More importantly, however, for the purpose of this discussion, invocation of the setAction method causes the JMenuItem object to be registered as a PropertyChange listener on the Action object.  Following this, when the enabled property, or any of the keyed properties of the Action object change, the JMenuItem object will be notified of the change.

The JMenuItem class is designed such that this will cause some of the corresponding properties on the JMenuItem object to change in order to track the change on the Action object.  (A JMenuItem object doesn't set or track all of the indexed properties.)

After the JMenuItem object has been properly prepared, it is added to the menu in Listing 11.

An alternative to invoking setAction

Listing 12 shown an alternative approach to invoking the setAction method on the new JMenuItem object.  (This approach appears to achieve the same result as the invocation of the setAction method.).
 

    //Put a JMenuItem on the menu. Set
    // its Action object in the
    // constructor. This is a 
    // different approach.
    JMenuItem mnuA2 = 
            new JMenuItem(actionObj02);
    menu.add(mnuA2);

Listing 12

The JMenuItem class has a constructor that accepts a reference to an Action object as a parameter, and according to the Sun documentation, "Creates a menu item whose properties are taken from the specified Action."

An understatement

It appears that the statement in the Sun documentation is something of an understatement.  In particular, it appears that constructing the JMenuItem object in this manner causes the action property of that object to be set to the Action object, just as though the setAction method were invoked on that object as in Listing 11.

As explained in the discussion of Listing 11, this involves much more than the Sun documentation statement would imply.  In particular, the Action object becomes an action listener on the JMenuItem object, and the JMenuItem also becomes a change listener on the Action object.

Registration of two action listeners

Registering an Action object on an action-aware component does not prohibit the registration of ordinary ActionListener objects on the same component.  This is illustrated in Listing 13.
 

    JButton butB1 = new JButton();

    butB1.addActionListener(
      new ActionListener(){
        public void actionPerformed(
                        ActionEvent e){
          System.out.println(
           "Ordinary Action Listener");
        }//end actionPerformed()
      }//end ActionListener
    );//end addActionListener

    butB1.setAction(actionObj01);

    toolBar.add(butB1);

Listing 13

Listing 13 instantiates a new JButton object, and then uses an anonymous inner class to register an ordinary ActionListener object on that component.

(If you are unfamiliar with anonymous inner classes, see Baldwin's Java Programming Tutorials.)
Then it invokes the setAction method on the same JButton object, which causes the specified Action object to also be registered as an action listener on the JButton object.

Two actionPerformed methods are invoked

Thereafter, when the JButton object is clicked with the mouse, causing an action event to be fired by the JButton object, the following two lines of text appear on the screen:

Action: actionObj01
Ordinary Action Listener

The first line of output text is produced by the actionPerformed method defined in the Action object (see Listing 2).

The second line of output text is produced by the actionPerformed method defined for the ordinary ActionListener object (see Listing 13).

Finish populating the toolbar

Listing 14 finishes populating the toolbar by placing another JButton object on the toolbar.
 

    JButton butB2 = new JButton();
    butB2.setAction(actionObj02);
    toolBar.add(butB2);

Listing 14




Page 4 of 6



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel