Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 最大化JFrame会导致MouseMoved事件停止触发_Java_Macos_Swing_Mouseevent - Fatal编程技术网

Java 最大化JFrame会导致MouseMoved事件停止触发

Java 最大化JFrame会导致MouseMoved事件停止触发,java,macos,swing,mouseevent,Java,Macos,Swing,Mouseevent,似乎我在Mac OS X上不断发现MouseMotion监听器的更多问题。我又举了一个小例子来说明这个问题 public class TestGUI extends JFrame { Panel panel; public TestGUI() { setSize(1000, 600); setLocationRelativeTo(null); panel = new Panel(); setDefaultCloseOperation(JFrame.EXIT_O

似乎我在Mac OS X上不断发现MouseMotion监听器的更多问题。我又举了一个小例子来说明这个问题

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()
来检查这一点

我在MacOSX10.8.5上使用JDK1.7


有问题的答案对我不适用。事实上,接受答案的测试用例在我的计算机上不起作用。

我可以使用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);
}
当您按下“+”符号时,窗口确实会最大化,从而使光标回到面板内部。但是,我没有收到
鼠标插入事件。因此,移动鼠标不会触发
mouseMoved
事件。就Swing而言,鼠标甚至还没有进入组件。 只有当再次将鼠标移到最大化窗口外并重新进入时,才会出现
mouseEntered
事件,并再次触发
mouseMoved


根据,它在JDK8中解决。在我的机器上进行了测试,事实上,切换到JDK8解决了这个问题。如果这不是您的选择,您可以尝试使用另一个问题中提到的变通方法。

如果问题中链接的答案没有帮助,那么您可以用另一种方法来解决这个问题

您可以使用
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
)来停止记录鼠标在窗口外的情况


我发现有可能需要使用
setPreferredSize
pack()
来计算边界尺寸。我不确定,但我相信在java 7+版本中会发生这种情况。

您的代码在我的Windows 7机器上运行良好。1+回答你的问题,让我们拭目以待,看看答案是什么。