在Mac OS X中最大化或完全筛选窗口后,Java停止捕获鼠标移动事件

当我通过按下OS X上的最大化按钮或全屏按钮放大窗口时,不再捕获鼠标移动事件(尽管拖动是)。

我在下面包含了一个演示程序,突出了该问题。 可以使用Java Tutorials网站上的MouseEventDemo Web start示例复制最大化问题。

经过一些故障排除后,我注意到如果鼠标离开窗口(例如,移动到窗口顶部以访问菜单栏)然后返回,则重新捕获鼠标移动。 看起来问题可能与调整动画大小期间鼠标位置和窗口之间的关系有关,因为鼠标在resize之前不在帧中,但是后来即使它不一定在过程中移动也是如此。

import java.awt.Window; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.lang.reflect.Method; import javax.swing.JFrame; import javax.swing.JLabel; public class Main implements MouseMotionListener { JLabel label = new JLabel("label"); public static void main(String[] args) { Main main = new Main(); main.init(); } public void init() { JFrame frame = new JFrame(); frame.setSize(640, 480); frame.setLocationRelativeTo(null); frame.getContentPane().add(label); frame.addMouseMotionListener(this); frame.setVisible(true); if (isMacOSX()) { enableFullScreenMode(frame); } } public void mouseDragged(MouseEvent e) { label.setText(e.toString()); } public void mouseMoved(MouseEvent e) { label.setText(e.toString()); } private static boolean isMacOSX() { return System.getProperty("os.name").indexOf("Mac OS X") >= 0; } public static void enableFullScreenMode(Window window) { try { Class clazz = Class.forName("com.apple.eawt.FullScreenUtilities"); Method method = clazz.getMethod("setWindowCanFullScreen", new Class[] { Window.class, boolean.class }); method.invoke(null, window, true); } catch (Throwable t) { t.printStackTrace(); } } } 

运行上面的代码应该显示标签何时更新和不更新。

我正在使用Java SE 7 [1.7.0_45]运行OS X版本10.9 Build 13A3017。

根据经验,如果在最大化时切换离开并返回应用程序,问题就会消失。 添加强制框架toFront()ComponentListener似乎工作。 另外,应该在事件派发线程上构造和操作Swing GUI对象。

 frame.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { frame.toFront(); } }); 

经测试:

 import java.awt.EventQueue; import java.awt.Window; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.lang.reflect.Method; import javax.swing.JFrame; import javax.swing.JLabel; /** @see http://stackoverflow.com/a/20054242/230513 */ public class Main implements MouseMotionListener { JLabel label = new JLabel("label"); public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { Main main = new Main(); main.init(); } }); } public void init() { final JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(label); frame.pack(); frame.setSize(640, 480); frame.setLocationRelativeTo(null); frame.setVisible(true); if (isMacOSX()) { enableFullScreenMode(frame); } frame.addMouseMotionListener(this); frame.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { frame.toFront(); } }); } @Override public void mouseDragged(MouseEvent e) { label.setText(e.toString()); } @Override public void mouseMoved(MouseEvent e) { label.setText(e.toString()); } private static boolean isMacOSX() { return System.getProperty("os.name").indexOf("Mac OS X") >= 0; } public static void enableFullScreenMode(Window window) { try { Class clazz = Class.forName("com.apple.eawt.FullScreenUtilities"); Method method = clazz.getMethod("setWindowCanFullScreen", new Class[]{Window.class, boolean.class}); method.invoke(null, window, true); } catch (Throwable t) { t.printStackTrace(); } } } 

Oracle回应了我提交的错误报告 ,在他们的评论中指出应该在Java 8中解决该问题。上面的代码使用OS X 10.9.2在1.8.0 JRE(build 1.8.0-b132)上按预期工作。

通过向框架添加windowStateListener并执行以下操作,我能够找到解决此问题最大化部分的方法:

 frame.addWindowStateListener(new WindowStateListener() { @Override public void windowStateChanged(WindowEvent e) { if (Frame.MAXIMIZED_BOTH == e.getNewState()) { frame.toBack(); frame.toFront(); } } }); 

如果你将它与来自trashgod的resize工作结合起来,你应该处于良好的状态。

事件mouseReleased,mouseClicked在使用jdk 1.6.0_65(yosemite)时不会被触发,对于jdk 1.8.0_25(yosemite)事件被触发以及事件是在jdk 1.6(特立独行)上触发的。 可能是什么问题?

java -version java version“1.6.0_65”Java(TM)SE运行时环境(版本1.6.0_65-b14-466.1-11M4716)Java HotSpot(TM)64位服务器VM(版本20.65-b04-466.1,混合模式)

windowActivated windowOpened mousePressed windowClosing windowDeactivated

java版“1.8.0_25”Java(TM)SE运行时环境(版本1.8.0_25-b17)Java HotSpot(TM)64位服务器VM(内置25.25-b02,混合模式)

windowActivated windowOpened mousePressed mouseReleased mouseClicked windowClosing windowDeactivated

import java.awt。 ; import java.awt.event。 ;

公共类TestMouseEventsOnYosemite {

 public static void main(String[] args) { TestFrame testFrame = new TestFrame(); testFrame.setVisible(true); testFrame.toFront(); } public static class TestFrame extends Frame implements WindowListener { public TestFrame() { setLayout(null); addNotify(); Button okButon = new Button(" Ok "); add(okButon); okButon.addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent event) { System.out.println("mouseReleased"); } public void mousePressed(MouseEvent event) { System.out.println("mousePressed"); } public void mouseClicked(MouseEvent event) { System.out.println("mouseClicked"); } } ); okButon.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent event) { System.out.println("keyPressed"); } } ); int dy = okButon.getPreferredSize().height; okButon.setBounds(30, 50, 100, dy); setSize(150, 150); addWindowListener(this); setResizable(true); okButon.requestFocusInWindow(); } public void windowActivated(WindowEvent e) { System.out.println("windowActivated"); } public void windowClosed(WindowEvent e) { System.out.println("windowClosed"); } public void windowDeactivated(WindowEvent e) { System.out.println("windowDeactivated"); } public void windowDeiconified(WindowEvent e) { System.out.println("windowDeiconified"); } public void windowIconified(WindowEvent e) { System.out.println("windowIconified"); } public void windowOpened(WindowEvent e) { System.out.println("windowOpened"); } public void windowClosing(WindowEvent e) { System.out.println("windowClosing"); } } 

}