1

I automatically generate a set of JMenuItem and add them to a JPopUpMenu on each right click event. The problem is that the action that I set for the menu item doesn't run when I press enter key on the selected menu. I can use the up/down keys for navigating on the menu, however, the action is run only by mouse click.

Here is the piece of code to create menu item:

private JMenuItem createMenuItem(TaskFactory tf, String title, boolean useCheckBoxMenuItem, String toolTipText) {

    enter code hereJMenuItem item;
    PopupAction action = new PopupAction(tf, title);
    if ( useCheckBoxMenuItem )
        item = new JCheckBoxMenuItem(action);
    else
        item = new JMenuItem(action);
    item.setEnabled(tf.isReady());
    item.setToolTipText(toolTipText);
    return item;
}

private class PopupAction extends AbstractAction {

    TaskFactory tf;
    PopupAction(TaskFactory tf, String title) {
        super( title );
        this.tf = tf;
    }
    public void actionPerformed(ActionEvent ae) {
        m_view.manager.execute(tf.createTaskIterator());
    }
}

I have tried setting focusable to true, but that didn't work. I have tried it on Mac 10.7 the Java version 1.6.0_33 and Ubuntu Java version 1.6.0_26. and I used the standard swing look and feel. When running on Mac: look and feel is[Aqua Look and Feel for Mac OS X - com.apple.laf.AquaLookAndFeel]

rozagh
  • 73
  • 1
  • 12

4 Answers4

2

Windows XP, JDK6_025, working with Substance, Metal, Windows, Nimbus

Edit1

on Key or Mouse pressed is fired isEnabled

Edit2

added MenuKeyListener,

NOTICE !!!!!

don't use MenuKeyListener for catching another KeyEvents as (Space) and are, otherwise generating sometimes spurious results, such as Unknown keyCode: 0x0 on ….

import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.MenuKeyEvent;
import javax.swing.event.MenuKeyListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.table.*;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.skin.BusinessBlueSteelSkin;

public class TableCheckBox extends JFrame {

    private static final long serialVersionUID = 1L;
    private JTable table;

    public TableCheckBox() {
        Object[] columnNames = {"Type", "Company", "Shares", "Price", "Boolean"};
        Object[][] data = {
            {"Buy", "IBM", new Integer(1000), new Double(80.50), false},
            {"Sell", "MicroSoft", new Integer(2000), new Double(6.25), true},
            {"Sell", "Apple", new Integer(3000), new Double(7.35), true},
            {"Buy", "Nortel", new Integer(4000), new Double(20.00), false}
        };
        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        table = new JTable(model) {

            private static final long serialVersionUID = 1L;

            @Override
            public Class getColumnClass(int column) {
                return getValueAt(0, column).getClass();
            }
        };
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane);
        createPopupMenu();
    }

    private void createPopupMenu() {
        MyMenuKeyListener myMenuKeyListener = new MyMenuKeyListener();
        JPopupMenu popup = new JPopupMenu();
        JMenuItem myMenuItem1 = new JMenuItem("cccccccccccccccccccccc");
        myMenuItem1.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                //System.out.println("Done myMenuItem1");
            }
        });
        myMenuItem1.getModel().addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                ButtonModel model = (ButtonModel) e.getSource();
                if (model.isArmed()) {
                    //System.out.println("isArmed");
                } else if (model.isEnabled()) {
                    //System.out.println("isEnabled");
                } else if (model.isPressed()) {
                    //System.out.println("isPressed");
                } else if (model.isRollover()) {
                    //System.out.println("isRollover");
                } else if (model.isSelected()) {
                    //System.out.println("isSelected");
                }
            }
        });
        myMenuItem1.addMenuKeyListener(myMenuKeyListener);

        JMenuItem myMenuItem2 = new JMenuItem("bbbbbbbbbbbbbbbbbbbbbb");
        myMenuItem2.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                //System.out.println("Done myMenuItem2");
            }
        });
        myMenuItem2.getModel().addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                ButtonModel model = (ButtonModel) e.getSource();
                if (model.isArmed()) {
                    //System.out.println("isArmed");
                } else if (model.isEnabled()) {
                    //System.out.println("isEnabled");
                } else if (model.isPressed()) {
                    //System.out.println("isPressed");
                } else if (model.isRollover()) {
                    //System.out.println("isRollover");
                } else if (model.isSelected()) {
                    //System.out.println("isSelected");
                }
            }
        });
        myMenuItem2.addMenuKeyListener(myMenuKeyListener);

        popup.add(myMenuItem1);
        popup.add(myMenuItem2);
        MouseListener popupListener = new PopupListener(popup);
        table.addMouseListener(popupListener);
        popup.setLightWeightPopupEnabled(false);
        PopupMenuListener popupMenuListener = new MyPopupMenuListener();
        popup.addPopupMenuListener(popupMenuListener);
    }

    private class PopupListener extends MouseAdapter {

        private JPopupMenu popup;

        PopupListener(JPopupMenu popupMenu) {
            popup = popupMenu;
        }

        @Override
        public void mousePressed(MouseEvent e) {
            maybeShowPopup(e);
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (table.getSelectedRow() != -1) {
                maybeShowPopup(e);
            }
        }

        private void maybeShowPopup(MouseEvent e) {
            if (e.isPopupTrigger()) {
                popup.show(e.getComponent(), e.getX(), e.getY());
            }
        }
    }

    private class MyMenuKeyListener implements MenuKeyListener {

        public void menuKeyTyped(MenuKeyEvent e) {
            MenuElement[] path = e.getPath();
            JMenuItem item = (JMenuItem) path[path.length - 1];
            System.out.println("Key typed: " + e.getKeyChar()
                    + ", " + MenuKeyEvent.getKeyText(e.getKeyCode())
                    + " on " + item.getText());
        }

        public void menuKeyPressed(MenuKeyEvent e) {
            MenuElement[] path = e.getPath();
            JMenuItem item = (JMenuItem) path[path.length - 1];
            System.out.println("Key typed: " + e.getKeyChar()
                    + ", " + MenuKeyEvent.getKeyText(e.getKeyCode())
                    + " on " + item.getText());
        }

        public void menuKeyReleased(MenuKeyEvent e) {
            MenuElement[] path = e.getPath();
            JMenuItem item = (JMenuItem) path[path.length - 1];
            System.out.println("Key typed: " + e.getKeyChar()
                    + ", " + MenuKeyEvent.getKeyText(e.getKeyCode())
                    + " on " + item.getText());
        }
    }

    private class MyPopupMenuListener implements PopupMenuListener {

        public void popupMenuCanceled(PopupMenuEvent popupMenuEvent) {
            //System.out.println("Canceled");
        }

        public void popupMenuWillBecomeInvisible(PopupMenuEvent popupMenuEvent) {
            //System.out.println("Becoming Invisible");
        }

        public void popupMenuWillBecomeVisible(PopupMenuEvent popupMenuEvent) {
            //System.out.println("Becoming Visible");
        }
    }

    public static void main(String[] args) {
        /*SwingUtilities.invokeLater(new Runnable() {

        public void run() {
        SubstanceLookAndFeel.setSkin(new BusinessBlueSteelSkin());
        }
        });*/
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
            /*UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());*/
        } catch (ClassNotFoundException ex) {
        } catch (InstantiationException ex) {
        } catch (IllegalAccessException ex) {
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                TableCheckBox frame = new TableCheckBox();
                frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocation(150, 150);
                frame.setVisible(true);
            }
        });
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I tried this code on my Mac and works perfectly (both enter and space bar are running action)! But I tried printing the change listener on my code, enter does not fire any changes! – rozagh Jun 22 '12 at 22:21
  • I also tried Nimbus look and feel but still menu doesn't listen to enter! – rozagh Jun 22 '12 at 22:38
1

AFAIK, that's just how the look 'n feel works. Buttons and menu items can be clicked by pressing the space bar. Enter is for clicking the default button.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks for the replu, the space bar does not work either! For me, both space bar or enter would be OK if they run the action. – rozagh Jun 22 '12 at 20:04
  • user1475727 please can you be concrete, which of NativeOS, Java version and used Look and Feel, because (@JB Nizet) could be right – mKorbel Jun 22 '12 at 20:09
  • I have tried it on Mac 10.7 the Java version 1.6.0_33 and Ubuntu Java version 1.6.0_26. and I used the standard swing look and feel. – rozagh Jun 22 '12 at 20:19
  • @user1475727 then you have waiting for real Swing & OSX (***nix) gurus, I'll update tags – mKorbel Jun 22 '12 at 20:22
1

This ImageApp appears to work correctly using Action for both items added to a menu bar and items added to a context menu via setComponentPopupMenu(). Either Enter or Space evokes the selected menu item from either the menu bar or the context menu.

As an aside, note the use of getMenuShortcutKeyMask() as a cross-platform MASK.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • @rozagh: I suspect the problem is in unseen code. If you can produce an [sscce](http://sscce.org/) that exhibits the problem, I'll try running it. Feel free to use my example as a foundation. – trashgod Jun 23 '12 at 15:56
  • The popup menu and menu items in my code are generated based on the mouse event position and is evoked using the 'show(x, y)' method. The menu cannot be attached to a specific component. Do you think using the 'show(x, y)' is the source of problem? – rozagh Jun 25 '12 at 18:47
  • Could be; `setComponentPopupMenu()` is certainly more convenient. If you do it the old way, don't forget `isPopupTrigger()`, as suggested [here](http://docs.oracle.com/javase/tutorial/uiswing/components/menu.html). – trashgod Jun 25 '12 at 23:18
0

You need to add a KeyListener to your JMenuItem, and set the item as focusable. Have your JMenuItem requesting focus with

JMenuItem.requestFocus();

When it has focus, the implemtation is easy

In your keylistener:

        @Override
        public void keyReleased(KeyEvent e) {
            if (e.getKeyCode() == e.VK_ENTER) {
                // do stuff
            }

        }
Jordon Biondo
  • 3,974
  • 1
  • 27
  • 37