问题
Is there any way to auto-select a jmenu within my jmenubar when the user's pressing the "ALT" key ? (Like windows softwares)
The problem is that the default behavior of my jframe, when the "ALT" key is pressed, is to show up a menu containing the following actions : restore, move, size, reduce, ...
What I want my java application to do, is to select my jmenu first item when "alt" is pressed. (Like it would do with a mnemonic : "alt + f")
回答1:
Add the action to the ActionMap
and InputMap
of your JRootPane
. See below:
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class MenuExample {
private void setupMenuKey(final JFrame frame) {
Action menuAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
JRootPane rootPane = frame.getRootPane();
JMenuBar jMenuBar = rootPane.getJMenuBar();
JMenu menu = jMenuBar.getMenu(0);
menu.doClick();
}
};
JRootPane rootPane = frame.getRootPane();
ActionMap actionMap = rootPane.getActionMap();
final String MENU_ACTION_KEY = "expand_that_first_menu_please";
actionMap.put(MENU_ACTION_KEY, menuAction);
InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true), MENU_ACTION_KEY);
}
private JFrame build() {
JFrame frame = new JFrame("Hello");
frame.setSize(300, 300);
JMenuBar bar = new JMenuBar();
List<String> letters = Arrays.asList("A", "B", "C");
for (int i = 0; i < 3; i++) {
JMenu menu = new JMenu("Menu " + i);
for (String string : letters) {
menu.add(new JMenuItem(String.format("Menu %s - %s", i, string)));
}
bar.add(menu);
}
frame.setJMenuBar(bar);
JButton b = new JButton("click");
JPanel p = new JPanel();
p.add(b);
frame.add(p);
setupMenuKey(frame);
return frame;
}
public static void main(String[] args) {
MenuExample menuExample = new MenuExample();
JFrame frame = menuExample.build();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
回答2:
Use actionmap and inputmap of JComponent to do this job. Since JFrame is not a descendant of JCompoenent i would suggest you adding JPanel to your jframe and then,
Action action = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
jMenu1.doClick();
}
};
jPanel1.getActionMap().put("myAction", action);
jPanel1.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, KeyEvent.ALT_DOWN_MASK), "myAction");
回答3:
I've found the response very useful, but also with a drawback.
Imagine you're using Cross PlatForm L&F (Metal) and you've defined mnemonics to all the menus; you know that those menus are invoked against pressing . So, if we put the solution provided by black panda the results on a pressing are first we watch the desired menu deployed but immediately after switches to the first menu.
I think that the best way would be on ALT pressing only the first menu should be selected but without showing its contents (Those contents shoud appear on a down key pressing). Is there any way to do this in Cross Platform L&F?.
Alternatively there is another way to proceed without any extra code. If we invoke the System L&F (Windows in my case) the ALT key behaves as desired. See stackoverflow question 13474555 for details.
回答4:
I have found just by using frame.setJMenuBar(jmenubar);
where frame
is your JFrame and jmenubar
is your JMenuBar, it'll automatically do this. You don't even have to add it to your layout manager.
来源:https://stackoverflow.com/questions/8657801/focus-on-first-jmenubar-item-on-alt-key-press