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

e4e*_*4e5 8 java macos swing

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

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

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

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

tra*_*god 7

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

frame.addComponentListener(new ComponentAdapter() {

    @Override
    public void componentResized(ComponentEvent e) {
        frame.toFront();
    }
});
Run Code Online (Sandbox Code Playgroud)

经测试:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


e4e*_*4e5 1

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