JMenuBar箭头键的工作方式与预期相反,因为componentOrientation设置为从右到左



setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT)应用于JMenuBar后,箭头键的行为开始与预期相反。当试图遍历键盘时,右箭头向左,左箭头向右。

顺便说一下,我在Windows10上使用Java11.0.12

这是代码:

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
@SuppressWarnings("serial")
public class MenuBarProblem extends JFrame {

private JMenuBar menuBar;

private JMenu firstMenu;
private JMenuItem a;
private JMenuItem b;

private JMenu secondMenu;
private JMenuItem c;
private JMenuItem d;

private JMenu thirdMenu;
private JMenuItem e;
private JMenuItem f;

public MenuBarProblem() {
this.setLayout(new BorderLayout());
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setSize(screenSize);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.firstMenu = new JMenu("first");
this.a = new JMenuItem("a");
this.b = new JMenuItem("b");
this.firstMenu.add(this.a);
this.firstMenu.add(this.b);

this.secondMenu = new JMenu("second");
this.c = new JMenuItem("c");
this.d = new JMenuItem("d");
this.secondMenu.add(this.c);
this.secondMenu.add(this.d);

this.thirdMenu = new JMenu("third");
this.e = new JMenuItem("e");
this.f = new JMenuItem("f");
this.thirdMenu.add(this.e);
this.thirdMenu.add(this.f);

this.menuBar = new JMenuBar();
this.menuBar.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); //Here is the reason
this.menuBar.add(this.firstMenu);
this.menuBar.add(this.secondMenu);
this.menuBar.add(this.thirdMenu);
this.setJMenuBar(this.menuBar);
}
}

这也是包含主要方法的主要类:

import java.lang.reflect.InvocationTargetException;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {

public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}

SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
MenuBarProblem test = new MenuBarProblem();
test.setVisible(true);
}
});
}
}

更新:这个问题原来是一个bug,现在它已经被添加到这里的bug数据库中。

同时,该问题已被视为一个错误(请参阅上文(,因此建议的解决方案是一个临时补丁,建立在WindowsLookAndFeel的内部实现之上。

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
@SuppressWarnings("serial")
public class MenuBarProblem extends JFrame {
private JMenuBar menuBar;
private JMenu firstMenu;
private JMenuItem a;
private JMenuItem b;
private JMenu secondMenu;
private JMenuItem c;
private JMenuItem d;
private JMenu thirdMenu;
private JMenuItem e;
private JMenuItem f;
private JMenu fourthMenu;
private JMenuItem g;
private JMenuItem h;
private KeyboardFocusManager keyboardFocusManager;
public MenuBarProblem() {
setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(400, 200));
add(panel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
firstMenu = new JMenu("first");
a = new JMenuItem("a");
b = new JMenuItem("b");
firstMenu.add(a);
firstMenu.add(b);
secondMenu = new JMenu("second");
c = new JMenuItem("c");
d = new JMenuItem("d");
secondMenu.add(c);
secondMenu.add(d);
thirdMenu = new JMenu("third");
e = new JMenuItem("e");
f = new JMenuItem("f");
thirdMenu.add(e);
thirdMenu.add(f);
fourthMenu = new JMenu("fourth");
g = new JMenuItem("g");
h = new JMenuItem("h");
fourthMenu.add(g);
fourthMenu.add(h);
menuBar = new JMenuBar();
menuBar.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); // Here is the reason
menuBar.add(firstMenu);
menuBar.add(secondMenu);
menuBar.add(thirdMenu);
menuBar.add(fourthMenu);
setJMenuBar(menuBar);
pack();
keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
keyboardFocusManager.addKeyEventDispatcher(new MSMKeyEventDispatcher());
}
private class MSMKeyEventDispatcher implements KeyEventDispatcher {
int index = -1;
private void select(int index) {
JMenu menu = menuBar.getMenu(index);
if (menu != null) {
MenuSelectionManager msm = MenuSelectionManager.defaultManager();
MenuElement path[] = new MenuElement[2];
path[0] = menuBar;
path[1] = menu;
msm.setSelectedPath(path);
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (MenuBarProblem.this.getFocusOwner() == null) {
return false;
}
if (e.getID() == KeyEvent.KEY_PRESSED) {
if (e.getKeyCode() == KeyEvent.VK_ALT) {
MenuSelectionManager msm = MenuSelectionManager.defaultManager();
if (msm.getSelectedPath().length == 0) {
index = 0;
select(index);
} else {
msm.setSelectedPath(null);
index = -1;
}
return true;
} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
if (index >= 0) {
--index;
if (index < 0) {
index = menuBar.getComponentCount() - 1;
}
select(index);
return true;
}
} else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
if (index >= 0) {
++index;
if (index >= menuBar.getComponentCount()) {
index = 0;
}
select(index);
return true;
}
}
}
return false;
}
}
}

附录:解决方案最简单的想法可能是KeyEventDispatcher切换接收到的KeyEvent的KeyCodes KeyEvent.VK_LEFT和KeyEvent.VK-RIGHT,并重新补丁更改后的KeyEvent。然而,事实证明,这绝对没有任何效果。

相关内容

最新更新