Java JLabel使用鼠标运动侦听器无法正常移动,为什么?

Java JLabel使用鼠标运动侦听器无法正常移动,为什么?,java,swing,Java,Swing,每当拖动鼠标时,我都需要相应地移动JLabel。 为什么在拖动时显示多个JLabel,而不是在正确的位置显示组件 public class Mover extends JFrame { private JPanel jPanel; private JLabel jLabel1; private JLabel jLabel2; private int myXX = 0; private int myYY = 0; public Mover() { setSize(500, 500);

每当拖动鼠标时,我都需要相应地移动JLabel。
为什么在拖动时显示多个JLabel,而不是在正确的位置显示组件

public class Mover extends JFrame 
{

private JPanel jPanel;
private JLabel jLabel1;
private JLabel jLabel2;
private int myXX = 0;
private int myYY = 0;

public Mover() {
    setSize(500, 500);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    jPanel = new JPanel(null);
    jLabel1 = new JLabel("label one");
    jLabel2 = new JLabel("label two");

    jLabel1.setBounds(100, 100, 100, 100);
    jLabel2.setBounds(100, 100, 100, 100);
    jLabel1.addMouseMotionListener(new MouseMotionListener() {

        @Override
        public void mouseMoved(MouseEvent e) {
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            System.out.println("Label One");
            myXX = e.getX() - (jLabel1.getWidth() / 2);
            myYY = e.getY() - (jLabel1.getHeight() / 2);
            jLabel1.setLocation(myXX, myYY);
            repaint();
        }
    });
    jLabel2.addMouseMotionListener(new MouseMotionListener() {

        @Override
        public void mouseMoved(MouseEvent e) {
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            System.out.println("Label Two");

            myXX = e.getX() - (jLabel2.getWidth() / 2);
            myYY = e.getY() - (jLabel2.getHeight() / 2);
            jLabel2.setLocation(myXX, myYY);
            repaint();
        }
    });
    jPanel.add(jLabel1);
    jPanel.add(jLabel2);
    add(jPanel);
    repaint();
    revalidate();
    setVisible(true);
}

public static void main(String args[]) {
    new Mover();
}
}
这个问题有什么有效的解决办法吗?

显然提前感谢。

MouseEvent信息与生成事件的组件(在本例中为标签)相关

这意味着
0x0
实际上是标签的左上角。您需要将事件的点信息转换为其父上下文,例如

Point p = e.getPoint();
p = SwingUtilities.convertPoint(e.getComponent(), p, e.getComponent().getParent());
您也不需要创建
myXX
myYY
实例字段,因为它们实际上只有驱动它们的鼠标事件的上下文

您还应该查看并确保在事件调度线程的上下文中启动您的程序

您也不需要为每个组件创建单独的侦听器,只需稍微巧妙地使用
MouseEvent
中的可用信息,就可以为所有组件使用单个侦听器并减少代码重复

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Mover extends JFrame {

    private JPanel jPanel;
    private JLabel jLabel1;
    private JLabel jLabel2;

    public Mover() {
        setSize(500, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jPanel = new JPanel(null);
        jLabel1 = new JLabel("label one");
        jLabel2 = new JLabel("label two");

        jLabel1.setBounds(100, 100, 100, 100);
        jLabel2.setBounds(100, 100, 100, 100);

        MouseMotionListener mover = new MouseMotionListener() {

            @Override
            public void mouseMoved(MouseEvent e) {
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                System.out.println("Label One");

                Component child = e.getComponent();
                Point p = e.getPoint();
                p = SwingUtilities.convertPoint(e.getComponent(), p, e.getComponent().getParent());

                int myXX = p.x - (child.getWidth() / 2);
                int myYY = p.y - (child.getHeight() / 2);
                child.setLocation(myXX, myYY);
                repaint();
            }
        };

        jLabel1.addMouseMotionListener(mover);
        jLabel2.addMouseMotionListener(mover);

        jPanel.add(jLabel1);
        jPanel.add(jLabel2);
        add(jPanel);
        setVisible(true);
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                new Mover();
            }
        });
    }
}

如果我没有指出直接从顶级容器(如
JFrame
扩展)进行扩展是一种不好的做法,会将您锁定在一个一次性容器中,使您在将来很难重复使用该容器或将其添加到其他容器中(如果您希望…),您并没有向其添加任何功能…

MouseeEvent基于生成它的本地组件上下文,也就是说,x/y位置相对于标签的x/y位置没有点调用
revalidate
,当您没有布局管理器时,没有什么需要重新验证的…哦,但是我们可以根据鼠标移动来移动标签的位置吗?是的,您需要将源点转换为它的父上下文…参见答案以获取示例…哦,哇!但是你能告诉我UIManager必须加入swing吗?不,我只是非常讨厌金属的外观和感觉;)是的,我知道了,但是在MouseEvent中生成子组件需要它吗?不,这比反复调用
MouseEvent\getComponent
…+1更简单,因为它是真正的解决方案,所以被接受了…)