我在最大化JFrame时遇到了一个处理鼠标位置的奇怪行为:
当我执行这个非常简单的代码时......
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
JMenuBar menubar = new JMenuBar();
JMenu menu = new JMenu("File");
menu.add(new JMenuItem("New"));
menubar.add(menu);
frame.setJMenuBar(menubar);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
...我通常可以点击File
(首次点击 - 按,发布) - > New
(第二次点击)。但是当我最大化JFrame并单击File
时 - 上下文菜单会立即在鼠标释放时消失。
此外,当我按住鼠标按钮 - 为了防止消失 - 我必须进一步移动鼠标以关注New
项目。
红点表示按下New
并按住鼠标按钮后我必须移动鼠标以对焦File
的区域(或多或少)。
我在使用“右键单击上下文菜单”时观察到相同的行为,例如右键单击JFreeChart中的图表时。
我认为这是JDK问题,因为我使用的是Oracle的JDK,但在安装OpenJDK后我得到了相同的结果。
有人观察到这种奇怪的行为吗?或者我错过了一些明显的东西?
我用:
答案 0 :(得分:3)
是的 - 这是JDK7中的一个错误,如@nIcE cOw所述。
我已经安装了JDK6,但我无法重现这个错误。
java version "1.6.0_23"
OpenJDK Runtime Environment (IcedTea6 1.11pre) (6b23~pre11-0ubuntu1.11.10.2)
OpenJDK 64-Bit Server VM (build 20.0-b11, mixed mode)
答案 1 :(得分:2)
当需要使用Oracle Java 7时(例如,使用JavaFX时),还有一种解决方法。只需将以下代码行添加到窗口/框架类中:
if (Arrays.asList("gnome-shell", "mate", "other...").contains(System.getenv("DESKTOP_SESSION"))) {
try {
Class<?> xwm = Class.forName("sun.awt.X11.XWM");
Field awt_wmgr = xwm.getDeclaredField("awt_wmgr");
awt_wmgr.setAccessible(true);
Field other_wm = xwm.getDeclaredField("OTHER_WM");
other_wm.setAccessible(true);
if (awt_wmgr.get(null).equals(other_wm.get(null))) {
Field metacity_wm = xwm.getDeclaredField("METACITY_WM");
metacity_wm.setAccessible(true);
awt_wmgr.set(null, metacity_wm.get(null));
}
}
catch (Exception x) {
x.printStackTrace();
}
}
答案 2 :(得分:0)
我想补充problemzebra给出的解决方案。
因为在Linux上使用任何swing应用程序(使用Cinnamon桌面),即使在Java 6(更新45)上,它仍然适用于我
每次移动窗口或调整窗口大小时,问题都会重新出现,因此每次窗口更改时都需要重新应用解决方法。我创建了以下类,并在创建新窗口时使用它:
class LinuxWindowFix implements WindowStateListener {
private final String desktop;
private Field metacity_wm;
private Field awt_wmgr;
private boolean applyFix;
private static LinuxWindowFix instance = new LinuxWindowFix();
public static LinuxWindowFix getInstance() {
return instance;
}
private LinuxWindowFix() {
applyFix = false;
List<String> linuxDesktops = Arrays.asList("gnome-shell", "mate", "cinnamon"); //add more desktop names here.
desktop = System.getenv("DESKTOP_SESSION");
if (desktop != null && linuxDesktops.contains(desktop.toLowerCase())) {
try {
Class<?> xwm = Class.forName("sun.awt.X11.XWM");
awt_wmgr = xwm.getDeclaredField("awt_wmgr");
awt_wmgr.setAccessible(true);
Field other_wm = xwm.getDeclaredField("OTHER_WM");
other_wm.setAccessible(true);
if (awt_wmgr.get(null).equals(other_wm.get(null))) {
metacity_wm = xwm.getDeclaredField("METACITY_WM");
metacity_wm.setAccessible(true);
applyFix = true;
}
} catch (Exception ex) {
//ignore
}
}
}
@Override
public void windowStateChanged(WindowEvent e) {
try {
awt_wmgr.set(null, metacity_wm.get(null));
} catch (Exception ex) {
//ignore
}
}
public void apply(Window w) {
if (!applyFix) {
return;
}
w.removeWindowStateListener(this);
w.addWindowStateListener(this);
}
}
只需为您创建的每个窗口调用此窗口,它就会按预期工作。
LinuxWindowFix.getInstance().apply(myWindow);