Gopal00005
Gopal00005

Reputation: 2151

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.

Upvotes: 1

Views: 432

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347214

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...

Upvotes: 2

Related Questions