2012-05-13 1 views
4

JFrame의 최대화 될 때 상황에 맞는 메뉴에서 "이동" 자바 스윙은 마우스 포인터가 JFrame의 극대화 때 스윙으로 마우스 위치를 처리하는 이상한 행동을 encoutered

나는이 아주 간단한 코드를 실행

...

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

빨간 점은 내가 File을 누르고 마우스 버튼을 누른 후 New에 초점을 내 마우스를 이동해야합니다 (자세한 이하) 영역을 나타냅니다.

예를 들어 JFreeChart에서 차트를 마우스 오른쪽 버튼으로 클릭 할 때 "마우스 오른쪽 버튼 클릭 상황에 맞는 메뉴"를 사용할 때와 동일한 문제가 발생했습니다.

오라클의 JDK를 사용했기 때문에 JDK 문제라고 생각했지만 OpenJDK를 설치 한 후에도 동일한 결과가 나타납니다.

누군가이 이상한 행동을 관찰 했습니까? 또는 나는 명백한 것을 놓치고 있는가?

내가 사용

  • 1.7.0_147-icedtea (또는 1.7.0_04을위한 자바 - 7 - 오라클)
  • 오픈 JDK 런타임 환경 (IcedTea7 2.0) (7 ~ b147-2.0-0ubuntu0.11.10 0.1)
  • 오픈 JDK 64 비트 서버 VM (21.0-B17, 혼합 모드)
  • 리눅스 민트 12 (리사) GNOME을 구축 3.2.1
+1

그것은, 이전 버전으로 돌아 오지하려고 자바 7 단지 버그, 아무것도 그리고 그것은 방금 언급 한 것처럼, 자바 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

당신을 (http://bugreport.sun.com/bugreport/index.jsp)보고 할 수 있습니다. – 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 쉘 또는 메이트 세션입니다. – problemzebra

+1

그렇다면 OTHER_WM의 값을 확인하는 이유는 무엇입니까? –

0

나는 problemzebra에서 주어진 해결책을 보완하고 싶습니다. 여전히 심지어 자바 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); 
관련 문제