Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4409290

JMenu.add(Action) ignores accelerator information

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 1.3.0
    • client-libs



      Name: boT120536 Date: 01/29/2001


      java version "1.3.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
      Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)


      This is an intentional duplicate of 4133256 (JMenu.add(Action) should request
      mnemonic AND accelerator from the Action object), which was incorrectly closed
      as a duplicate of 4138691 (Action object could use a predefined ACCELERATOR_KEY
      property).

      The crux of the issue is the fact that JMenu.add() ignores a defined
      accelerator. If you create an Action which specifies an accelerator, and then
      add() the action to a JMenu, the created JMenuItem does not have an
      accelerator. Despite the assertions of the individual who evaluated 4133256
      (which was not submitted by me, incidentally), I consider this to be clearly
      erroneous behavior, as it is both utterly stupid and requires the programmer to
      come up with creative workarounds just to get a simple accelerator working

      This issue should be reopened and resolved.


      Test case demonstrating both broken behavior and workaround:

      ---- TestCase.java ----

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

      class TestCase {
          static class ExitAction extends AbstractAction {
              public ExitAction() {
                  super("Exit");
                  putValue(MNEMONIC_KEY, new Integer('x'));
                  putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke('X',
      KeyEvent.ALT_MASK));
              }
              
              
              public void actionPerformed(ActionEvent e) {
                  System.exit(0);
              }
          }
          
          
          public static void main(String[] arg) {
              JFrame f = new JFrame("Demo");
              Action exitAction = new ExitAction();
              
              JMenuBar menubar = new JMenuBar();
              
              JMenu menu = new JMenu("Broken");
              menu.setMnemonic('B');
              menu.add(exitAction);
              // exitAction has a defined accelerator of Alt-X. The existing JMenu
      implementation
              // completely ignores this.
              menubar.add(menu);

              JMenu fixedMenu = new JMenu("Fixed") {
                  protected JMenuItem createActionComponent(Action action) {
                      JMenuItem result = super.createActionComponent(action);
                      result.setAccelerator((KeyStroke)
      action.getValue(Action.ACCELERATOR_KEY));
                      // shouldn't have to subclass JMenu and override
      createActionComponent to
                      // get it to pay attention to the accelerator, but I don't know
      of a simpler
                      // way to do it (and even if a simpler workaround exists, it's
      still a
                      // workaround...)
                      
                      return result;
                  }
              };
              fixedMenu.setMnemonic('F');
              fixedMenu.add(exitAction);
              menubar.add(fixedMenu);
              
              f.setJMenuBar(menubar);
              
              JLabel text = new JLabel("<html><font color=\"black\">Both 'Broken' and
      'Fixed' " +
                                       "contain the exact same Action object.<br>" +
                                       "'Broken' is a plain-vanilla JMenu object which
      ignores the " +
                                       "accelerator defined in the Action.<br>" +
                                       "'Fixed' is an anonymous subclass of JMenu
      which demonstrates " +
                                       "both the correct behavior<br>" +
                                       "and how to fix it.</font></html>");
              text.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
              text.setForeground(Color.black);
              f.getContentPane().add(text);
              
              f.pack();
              Dimension screenSize = f.getToolkit().getScreenSize();
              f.setLocation((screenSize.width - f.getWidth()) / 2,
                            (screenSize.height - f.getHeight()) / 2);
              f.show();
          }
      }
      (Review ID: 115978)
      ======================================================================

            mdavidsosunw Mark Davidson (Inactive)
            bonealsunw Bret O'neal (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: