2012-05-13 37 views
4

我JFrame的最大化时encoutered由摆动处理鼠标位置一个奇怪的行为时,JFrame的最大化:的Java 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 - 上下文菜单立即在鼠标释放时消失。 此外,当我按住鼠标按钮 - 防止失踪 - 我必须进一步移动我的鼠标以专注于New项目。

mouse shift

红点代表区(或多或少),我必须把我的鼠标专注于NewFile并保持鼠标按钮之后。

我在使用“右键单击上下文菜单”时观察到相同的行为,例如右键单击来自JFreeChart的图表时。

我认为这是JDK问题,因为我使用Oracle的JDK,但安装OpenJDK后,我得到了相同的结果。

有人观察到这种奇怪的行为吗?还是我错过了明显的东西?

我使用:

  • 1.7.0_147-的IcedTea(或1.7.0_04为Java -7-预言)
  • OpenJDK的运行时环境(IcedTea7 2.0)(7〜b147-2.0-0ubuntu0.11.10 0.1)
  • OpenJDK的64位服务器VM(构建21.0-B17,混合模式)
  • Linux Mint的12(丽萨)GNOME 3.2.1
+1

在我看来,这只是一个Java 7的错误,没有别的,尽量回来任何以前的版本,它不存在,Java 7中有很多错误,像一个你刚刚提到:( –

回答

3

是 - 这是在JDK7一个错误为@没有提到。

我已经安装了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) 
+0

你可以报​​告它[这里] – Tharwen

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

这段代码是基于workaround from the Netbeans developers

+0

它是做什么的? –

+0

它将当前的AWT窗口管理器类设置为用于Metacity WM的类,如果桌面会话是Gnome Shell或Mate会话 – problemzebra

+1

那么为什么它会检查OTHER_WM的值? –

0

我想补充problemzebra给出的解决方案。

由于它仍然发生,我在Linux上使用(使用肉桂桌面),甚至在Java 6的任何Swing应用程序(更新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);