Java JLabel使用鼠标运动侦听器无法正常移动,为什么?
每当拖动鼠标时,我都需要相应地移动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,而不是在正确的位置显示组件
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更简单,因为它是真正的解决方案,所以被接受了…)