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

在Mac OS X中最大化或完全屏蔽窗口后,Java停止捕获鼠标移动事件,java,macos,swing,Java,Macos,Swing,在OSX上,当我通过按最大化按钮或全屏按钮来放大窗口时,鼠标移动事件不再被捕获(尽管可以拖动) 我在下面提供了一个演示程序,突出了这个问题。可以使用上的复制最大化问题 经过一些故障排除,我注意到,如果鼠标离开窗口(例如,移动到窗口顶部以访问菜单栏),然后返回,则会重新捕获鼠标移动。问题似乎与调整动画大小期间鼠标位置和窗口之间的关系有关,因为在调整大小之前,鼠标不在帧中,但在调整大小之后,即使在调整过程中鼠标不一定移动 import java.awt.Window; import java.awt

在OSX上,当我通过按最大化按钮或全屏按钮来放大窗口时,鼠标移动事件不再被捕获(尽管可以拖动)

我在下面提供了一个演示程序,突出了这个问题。可以使用上的复制最大化问题

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

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.awt.Window;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseMotionListener;
导入java.lang.reflect.Method;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
公共类Main实现MouseMotionListener{
JLabel标签=新的JLabel(“标签”);
公共静态void main(字符串[]args){
Main Main=新Main();
main.init();
}
公共void init(){
JFrame=新JFrame();
帧设置大小(640480);
frame.setLocationRelativeTo(空);
frame.getContentPane().add(标签);
frame.addMouseMotionListener(此);
frame.setVisible(true);
if(isMacOSX()){
启用全屏模式(帧);
}
}
公共无效鼠标标记(鼠标事件e){
label.setText(例如toString());
}
public void mouseMoved(MouseEvent e){
label.setText(例如toString());
}
私有静态布尔isMacOSX(){
返回System.getProperty(“os.name”).indexOf(“Mac os X”)>=0;
}
公共静态无效启用FullScreenMode(窗口){
试一试{
Class clazz=Class.forName(“com.apple.eawt.FullScreenUtilities”);
方法Method=clazz.getMethod(“setWindowCanFullScreen”,新类[]{Window.Class,boolean.Class});
调用(null,window,true);
}捕获(可丢弃的t){
t、 printStackTrace();
}
}
}
运行上面的代码应该会显示标签何时更新,何时不更新


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

根据经验,如果在最大化的同时切换到应用程序,问题就会消失。添加一个
ComponentListener
,强制框架
toFront()
似乎可以工作。另一方面,Swing GUI对象应该只在服务器上构建和操作

经测试:

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();
        }
    }
}
导入java.awt.EventQueue;
导入java.awt.Window;
导入java.awt.event.ComponentAdapter;
导入java.awt.event.ComponentEvent;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseMotionListener;
导入java.lang.reflect.Method;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
/**@见http://stackoverflow.com/a/20054242/230513 */
公共类Main实现MouseMotionListener{
JLabel标签=新的JLabel(“标签”);
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
Main Main=新Main();
main.init();
}
});
}
公共void init(){
最终JFrame=新JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
框架。添加(标签);
frame.pack();
帧设置大小(640480);
frame.setLocationRelativeTo(空);
frame.setVisible(true);
if(isMacOSX()){
启用全屏模式(帧);
}
frame.addMouseMotionListener(此);
frame.addComponentListener(新的ComponentAdapter(){
@凌驾
公共无效组件已恢复(组件事件e){
frame.toFront();
}
});
}
@凌驾
公共无效鼠标标记(鼠标事件e){
label.setText(例如toString());
}
@凌驾
public void mouseMoved(MouseEvent e){
label.setText(例如toString());
}
私有静态布尔isMacOSX(){
返回System.getProperty(“os.name”).indexOf(“Mac os X”)>=0;
}
公共静态无效启用FullScreenMode(窗口){
试一试{
Class clazz=Class.forName(“com.apple.eawt.FullScreenUtilities”);
Method=clazz.getMethod(“setWindowCanFullScreen”,
新类[]{Window.Class,boolean.Class});
调用(null,window,true);
}捕获(可丢弃的t){
t、 printStackTrace();
}
}
}

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

我通过在框架中添加WindowsStateListener并执行以下操作,找到了解决此问题最大化部分的方法:

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

如果您将此与垃圾神的调整大小工作结合起来,您应该处于良好状态。

当使用jdk 1.6.0_65(约塞米蒂)时,不会触发MouseRelease、mouseClicked事件,而对于jdk 1.8.0_25(约塞米蒂),则会触发事件,而且该事件也是在jdk 1.6(maverick)上触发的。可能是什么问题

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

窗口激活 窗口打开 鼠印 窗口关闭 窗口停用

java版本“1.8.0_25” Java(TM)SE运行时环境(build 1.8.0_25-b17) Java HotSpot(TM)64位服务器虚拟机(构建25.25-b02,混合模式)

窗口激活 窗口打开 鼠印 滑鼠 滑鼠 窗口关闭 窗口
frame.addWindowStateListener(new WindowStateListener()
{
    @Override
    public void windowStateChanged(WindowEvent e)
    {
        if (Frame.MAXIMIZED_BOTH == e.getNewState())
        {
            frame.toBack();
            frame.toFront();
        }
    }
});
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");
    }
}