SWT issues with cascaded MenuItem accelerators

2019-06-09 19:32发布

The MenuItem objects having a SWT.CASCADE style (like 'File') won't drop down when the accelerator key combo is pressed.

In the example below, pressing Alt-F triggers the Selection event (I see "File" in the console) but the menu itself won't drop down. I couldn't find a method to programmatically make the menu drop down either. Any idea?

(The package I'm using is org.eclipse.swt.win32.win32.x86_64_3.100.0.v4233d.jar provided with the current version of Eclipse Juno.)

public class MenuTest {
    public static void main(String[] args) {
        Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());

        Menu menu = new Menu(shell, SWT.BAR);

        MenuItem item = new MenuItem(menu, SWT.CASCADE);
        item.setText("File");
        item.setAccelerator(SWT.ALT | 'F');
        Menu dropMenu = new Menu(shell, SWT.DROP_DOWN);

        item.setMenu(dropMenu);
        item.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                System.out.println("File");
            }
        });

        item = new MenuItem(dropMenu, SWT.NULL);
        item.setText("Close");
        item.setAccelerator(SWT.ALT | SWT.F4);
        item.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                System.out.println("Close");
                shell.dispose();
            }
        });

        shell.setMenuBar(menu);

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }
}

标签: java menu swt
1条回答
等我变得足够好
2楼-- · 2019-06-09 20:12

There is nothing wrong with your code and it is working as expected. By default on Windows OS, the Menu bars receive input focus when users press the Alt key and they lose input focus with the Esc key (see Keyboard accessibility section).

Now an accelerator is like a hot key/combination which is there to make ones life easier. In your scenario, when you press the ALT + F then default behavior of ALT of setting focus on the menu is over-ridden. And, that is why the menu listener is fired but the drop down menu is not shown.

Possible Solution

  1. Instead of item.setAccelerator(SWT.ALT | 'F'); do something like this item.setAccelerator(SWT.MOD1 | 'F');. Where MOD1, MOD2 .. MOD4 are the keyboard and/or mouse event mask indicating that the MOD1 key was pushed on the keyboard when the event was generated.
  2. On Windows OS you need not to set an accelerator for topmost level menu. Instead use mnemonic. For example, item.setText("&File");. See javadoc of setText() for more details.
  3. Or, more drastically How to disable normal behaviour of Alt key? (its a C++ solution)

Result of mnemonic

See the underline under the F of File.

enter image description here

查看更多
登录 后发表回答