2014-10-11 52 views
1

似乎我在Mac OS X上一直髮現MouseMotion偵聽器的更多問題。我做了另一個小例子來說明問題。使JFrame最大化導致MouseMoved事件停止觸發

public class TestGUI extends JFrame { 

Panel panel; 

public TestGUI() 
{ 
    setSize(1000, 600); 
    setLocationRelativeTo(null); 
    panel = new Panel(); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    getContentPane().add(panel); 
    setVisible(true); 
} 

class Panel extends JPanel 
{ 
    private Point mouseLocation = new Point(); 
    public Panel() 
    { 
     addMouseMotionListener(new MouseAdapter() { 
      @Override 
      public void mouseMoved(MouseEvent e) 
      { 
       mouseLocation = e.getPoint(); 
       repaint(); 
      } 
     }); 
     setVisible(true); 
    } 

    @Override 
    protected void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 
     g.setColor(Color.BLACK); 
     g.drawString("(" + mouseLocation.x + "," + mouseLocation.y + ")", 100, 100); 
    } 
} 

public static void main(String[] args) { 
    new TestGUI(); 
} 
} 

我不知道,如果這發生在Windows,因爲我現在還沒有進入到Windows電腦,但OS X會發生以下情況:

點擊綠色的「+」,以最大限度地提高該窗口會使窗口最大化,並因此導致鼠標指針回到畫布區域。但是,如果您不點擊,說明鼠標位置的文本將停止更新。

我知道這不是失去焦點的窗口:我通過在面板中添加一個focusAdapter並在該方法中添加了一個System.out.println()來檢查此問題。

我使用的是Mac OS X 10.8.5

this問題的答案JDK 1.7沒有爲我工作。事實上,接受答案上的測試用例在我的電腦上不起作用。

+0

您的代碼在我的Windows 7機器上正常工作。 1+來回答你的問題,讓我們拭目以待。 – 2014-10-11 03:04:10

回答

0

如果在問題中鏈接的答案沒有幫助,那麼您可以通過其他方式解決此問題。

而不是使用mouseMotionAdapter(或Listener)的(如果你喜歡或其他類型的定時器),您可以改用ScheduledExecutorService,得到以恆定的速度,鼠標的位置。窗口甚至不必爲你做這件事。

下面的小程序演示了最大化窗口對跟蹤鼠標位置沒有任何影響。

public class TestGUI extends JFrame { 

Panel panel; 
Point mouseLocation = new Point(); 
Dimension borderSize = new Dimension(); 
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(); 
public TestGUI() 
{ 
    setSize(1000, 600); 
    setLocationRelativeTo(null); 
    panel = new Panel(); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    getContentPane().add(panel); 
    setVisible(true); 
    borderSize.setSize(getSize().width - getContentPane().getSize().width, getSize().height - getContentPane().getSize().height); 
    ex.schedule(new UpdatingService(), 10, TimeUnit.MILLISECONDS); 
} 

class Panel extends JPanel 
{ 
    public Panel() 
    { 
     setVisible(true); 
    } 

    @Override 
    protected void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 
     g.setColor(Color.BLACK); 
     g.drawString("(" + mouseLocation.x + "," + mouseLocation.y + ")", 100, 100); 
    } 
} 

private void checkMouse() 
{ 
    mouseLocation.x = MouseInfo.getPointerInfo().getLocation().x - this.getLocationOnScreen().x - borderSize.width; 
    mouseLocation.y = MouseInfo.getPointerInfo().getLocation().y - this.getLocationOnScreen().y - borderSize.height; 
    repaint(); 
} 

class UpdatingService implements Runnable 
{ 
    @Override 
    public void run() 
    { 
     checkMouse(); 
     ex.schedule(new UpdatingService(), 10, TimeUnit.MILLISECONDS); 
    } 
} 

public static void main(String[] args) { 
    new TestGUI(); 
} 
} 

這裏的程序是如何工作的:首先,它計算的窗口邊框的大小,這從隨電腦而不同。然後每10毫秒ScheduledExecutorService獲得鼠標在屏幕上的位置(這可能太頻繁,拖延時間並查看是否有最佳時間)。首先在整個屏幕上找到鼠標的位置,然後減去JFrame的位置,然後減去邊框的粗細。

值得注意的是,這個程序繼續跟蹤窗口外的鼠標,但是如果鼠標在窗口之外,可以寫一個簡單的if語句(或者可以使用MouseAdapter)來停止錄製。

我發現使用setPreferredSizepack()以使邊界尺寸計算起作用是可能的。我不知道,但我相信這發生在Java版本7+

2

我可以使用JDK1.7在OS X 10.9.3上重現該問題。

我看到的情況是,當您將鼠標移動到包含綠色'+'符號的窗口裝飾條時,鼠標正在離開面板。這可以通過附加MouseListener

public Panel() 
{ 
    addMouseListener(new MouseAdapter() { 
    @Override 
    public void mouseEntered(MouseEvent e) { 
     System.out.println("TestGUI.Panel.mouseEntered"); 
    } 

    @Override 
    public void mouseExited(MouseEvent e) { 
     System.out.println("TestGUI.Panel.mouseExited"); 
    } 
    }); 
    addMouseMotionListener(new MouseAdapter() { 
    @Override 
    public void mouseMoved(MouseEvent e) 
    { 
     mouseLocation = e.getPoint(); 
     repaint(); 
    } 
    }); 
    setVisible(true); 
} 

當你按下「+」符號可以看到,該窗口將最大化確實導致光標找回面板內。但是,我沒有收到mouseEntered事件。就Swing而言,移動鼠標不會觸發mouseMoved事件,鼠標甚至沒有輸入組件。 只有當我的鼠標再次移動到最大化窗口之外並重新進入時,我纔會收到mouseEntered事件,並且mouseMoved再次被觸發。

根據this question,在JDK8中解決。在我的機器上進行了測試,實際上切換到JDK8解決了這個問題。如果這不是您的選擇,您可以嘗試使用其他問題中提到的解決方法。

相關問題