简体   繁体   中英

JLabel is not moving properly using mouse motion listener, Why?

Whenever I draggs mouse I need to move JLabel accordingly.
Why it shows multiple JLabel while dragging and not showing the component at proper location ?

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();
}
}

Is there any perfact solution of this problem ?
obviously Thanks in advance.

The MouseEvent information is contextual to the component that generated the event, in this case, the labels.

This means that 0x0 is actually the top/left corner of the label. You need to convert the point information of the event to it's parent context, for example...

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

You, also, don't need to make myXX or myYY instance fields, as they only ever really have context to the mouse event that is driving them.

You should also take a look at Initial Threads and make sure you're launching your program within the context of the Event Dispatching Thread...

You also don't need to create a separate listener for each component, with just a little bit of clever use of the available information from the MouseEvent you can use a single listener for all the components and reduce the code duplication...

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();
            }
        });
    }
}

I'd be doing you a disservice if I didn't point out that extending directly from a top level container like JFrame is bad practice and will lock you into a single use container, making it difficult to re-use the container in the future or add it to other containers should you so wish to...besides, you're not really adding any functionality to it...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM