2

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")

skaffman
  • 398,947
  • 96
  • 818
  • 769
Jsncrdnl
  • 3,005
  • 5
  • 28
  • 43
  • 1
    On the Windows applications that I use (and in my Java applications) the System Menu containing the "restore, move, size..." actions is display when Alt+Space is used. On my windows applications if I just use Alt, then the first menu on the menu bar is highlighted when the Alt key is released (not pressed). So your behaviour and require both seem non standard. Post your [SSCCD](http://www.sscce.org) which demonstrate your current problem with the Alt key. – camickr Dec 28 '11 at 17:59

4 Answers4

7

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);
    }


}
black panda
  • 2,842
  • 1
  • 20
  • 28
0

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.

  • 2
    This should be its own question with a reference back to this one, not an answer to this question. – ricksmt Dec 07 '13 at 01:37
0

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.

Cg2916
  • 1,117
  • 6
  • 23
  • 36
0

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");
Pragalathan M
  • 1,673
  • 1
  • 14
  • 19