Java – how do I set the accelerator for the JMenu submenu?
I have a user request to add the accelerator to the submenu (JMenu), which will allow the user to press the shortcut and "collapse" the corresponding submenu to display the menu items it contains
I don't remember everyone seeing such a thing (in Java or any other language) Our application is written in Java using swing We have many jmenuitems with accelerators, but when I try to add accelerators to jmenus, I get the following exception:
java. Lang. error: setaccelerator() is not defined for JMenu Use setmnemonic() instead
I tried menudemo! The code further tests this
This is what I tried:
//a submenu menu.addSeparator(); submenu = new JMenu("A submenu"); submenu.setMnemonic(KeyEvent.VK_S); submenu.setAccelerator(Keystroke.getKeystroke(KeyEvent.VK_U,InputEvent.CTRL_MASK));
The last line is the one I added, causing an exception
I've tried a lot of Google searches, but what I can find is an article on how to add an accelerator to jmenuitem
It seems that JMenu does not support this native Is there a solution to this behavior?
Solution
Another option is to override the accelerator get / set and reproduce the jmenuitem behavior Then the UI will do the rest
It is important to trigger property changes and set a consistent get / set for the accelerator The advantage of this solution is that it also provides visual indication of shortcuts / accelerators
This is a small demo code:
import java.awt.event.KeyEvent; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.Keystroke; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class TestMenu { protected void initUI() { JFrame frame = new JFrame(TestMenu.class.getSimpleName()); frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE); JMenuBar bar = new JMenuBar(); JMenu topMenu = new JMenu("Top Menu"); JMenu subMenu = new JMenu("Sub menu") { private Keystroke accelerator; @Override public Keystroke getAccelerator() { return accelerator; } @Override public void setAccelerator(Keystroke keystroke) { Keystroke oldAccelerator = accelerator; this.accelerator = keystroke; repaint(); revalidate(); firePropertyChange("accelerator",oldAccelerator,accelerator); } }; subMenu.setAccelerator(Keystroke.getKeystroke(KeyEvent.VK_F4,KeyEvent.CTRL_MASK)); JMenuItem item1 = new JMenuItem("Item 1"); JMenuItem item2 = new JMenuItem("Item 2"); subMenu.add(item1); subMenu.addSeparator(); subMenu.add(item2); topMenu.add(subMenu); bar.add(topMenu); frame.setJMenuBar(bar); frame.setSize(400,300); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokelater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (illegalaccessexception e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedLookAndFeelException e) { // TODO Auto-generated catch block e.printStackTrace(); } new TestMenu().initUI(); } }); } }