Reputation: 2151
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
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