在最大化JFrame时,我遇到了Swing处理鼠标位置的奇怪行为:
当我执行这个非常简单的代码…
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
– 上下文菜单立即消失在鼠标释放。 此外,当我按住鼠标button – 以防止失踪 – 我必须进一步移动鼠标以专注于New
项目。
红点表示区域(或多或less),在按下File
并按住鼠标button之后,必须将鼠标移动到New
位置。
在使用“右键单击上下文菜单”时,例如右键单击JFreeChart的图表时,我观察到了相同的行为。
我认为这是JDK的问题,因为我使用Oracle的JDK,但安装OpenJDK后,我有相同的结果。
有人观察到这种奇怪的行为吗? 还是我错过了明显的东西?
我用:
是的 – 这是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)
当需要使用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(); } }
此代码片段基于Netbeans开发人员的解决方法 。
我想补充problemzebra给出的解决方案。
因为在Linux上(使用Cinnamon桌面)任何swing应用程序仍然会发生,即使在Java 6(更新45)
每次移动窗口或重新调整窗口大小时,都会重新出现问题,因此每次窗口更改时都需要重新应用解决方法。 我创建了以下类,并在创建新窗口时使用它:
class LinuxWindowFix implements WindowStatelistner { 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.removeWindowStatelistner(this); w.addWindowStatelistner(this); } }
只需在创建的每个窗口中调用它,它就会按预期工作。
LinuxWindowFix.getInstance().apply(myWindow);