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.