MouseMotionListener 似乎闹鬼

Posted

技术标签:

【中文标题】MouseMotionListener 似乎闹鬼【英文标题】:MouseMotionListener appears to be Haunted 【发布时间】:2021-02-25 04:31:17 【问题描述】:

我刚刚学习 java,我有一个项目,我希望能够用鼠标在窗口周围移动 JLabel。

我建立了一个名为BasicWindow1的类,实现了一个MouseMotionListener,实例化了一个JFrame容器,在JFrame中添加了一个JLabel,设置了一个mouseDragged方法,将JLabel的setBounds方法与MouseEvent信息挂钩,编译它跑了……

但是……

当我拖动 JLabel 时,第二个 GHOST 标签出现在其上方,并与它的虚拟兄弟一起愉快地移动。

我已经包含了下面的代码,我希望有人会感兴趣并理顺我。我猜这可能是一个简单的初学者错误,但它让我发疯了。

在调试级别,我在 mouseDragged 方法中插入了一个带有 MouseEvent 的 println(e),它显示 MOUSE_DRAGGED x,y 元素在 2 个不同的 x,y 路径之间振荡,一个用于 GHOST,一个用于它的虚拟兄弟。

感谢收看, 迈克

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class BasicWindow1 implements MouseMotionListener 

   JFrame jf = new JFrame();
   JLabel label2 = new JLabel("label2");
      
   public BasicWindow1(String string) 

      //JFrame
      jf.setTitle(string);
      jf.setSize(400,400);   
      jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      jf.setLayout(null);
      jf.setVisible(true);

      label2.setOpaque(true);
      label2.setBackground(Color.cyan);
      label2.setBounds(0,150,75,25);
      label2.addMouseMotionListener(this);
      jf.add(label2);
          
   //end constructor
      
   public void mouseDragged(MouseEvent e) 
      label2.setBounds(e.getX(),e.getY(),75,25);
      System.out.println("e =  " + e); 
  
   public void mouseMoved(MouseEvent e) 

   public static void main(String[] args) 
      BasicWindow1 mybw = new BasicWindow1("Basic Window for Stack Overflow");
   

【问题讨论】:

一定是因为getY()和getYOnScreen()的区别。后者没有振荡(尽管偏移量有点偏)。它背后可能有一个与“事件相对于源组件的位置”有关的逻辑,但我刚刚醒来。以下是创建draggable component 的方法。 【参考方案1】:

您的问题是您将MouseMotionListener 添加到了错误的组件中。您需要将其添加到label2 的父级,即jf 的内容窗格。

试试下面的代码。

import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class BasicWindow1 implements MouseMotionListener 

    JFrame jf = new JFrame();
    JLabel label2 = new JLabel("label2");

    public BasicWindow1(String string) 

        // JFrame
        jf.setTitle(string);
        jf.setSize(400, 400);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLayout(null);
        jf.setVisible(true);

        label2.setOpaque(true);
        label2.setBackground(Color.cyan);
        label2.setBounds(0, 150, 75, 25);
        jf.getContentPane().addMouseMotionListener(this); // CHANGE HERE
        jf.add(label2);

    // end constructor

    public void mouseDragged(MouseEvent e) 
        label2.setLocation(e.getX(), e.getY()); // CHANGE HERE
    

    public void mouseMoved(MouseEvent e) 
    

    public static void main(String[] args) 
        BasicWindow1 mybw = new BasicWindow1("Basic Window for Stack Overflow");
    

方法getX()getY(),在类MouseEvent 中,返回鼠标指针在您添加MOuseMotionListener 的组件的坐标空间中的位置。在您的情况下,这是鼠标指针在 JLabel 内的位置,但这不是您想要的。您希望鼠标指针的位置在要拖动JLabel 的组件的坐标空间中,其中JFrame 或更准确地说是JFrame 的内容窗格。

有关替代解决方案,请参阅dragging a jlabel around the screen

【讨论】:

以上是关于MouseMotionListener 似乎闹鬼的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DragHandler exportAs Drag 禁用了我的 MouseMotionListener?

如何将自定义的 MouseMotionListener 添加到 JPanel?

MouseMotionListener 不会将坐标传输到 Canvas

Java 鼠标坐标显示事件监听MouseMotionListener

十三周总结

在 iOS AVPlayer 中,似乎缺少 addPeriodicTimeObserverForInterval