如何防止JLabel职位重置?

我有一个包含11个JLabel的JPanel,每个JLabel都注册了一个像MouseBans这样的MouseMotionListener(由Netbeans生成):

label1.addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseMotionEvent evt){ label1MouseDragged(evt); } 

和单个labelXMouseDragged方法包含(例如):

 label1.setLocation(label1.getParent().getMousePosition()); 

该小组与其他各种控制措施一起住在另一个小组内。 我发现我可以在面板内拖动我的标签(我的方法正确检查边界,但为了简单起见,我已将它们留在上面)。 但是,如果在内部面板内或父面板内的任何非控件上单击鼠标,则会重置标签的位置。 是什么导致这种情况发生? 我没有在其他任何地方注册的任何类型的mouseListener,如果我单独创建这个面板,我似乎没有点击问题。

你可以通过使用null布局来实现这一点,但是我对于null布局有一个pathalogical不喜欢,太多的东西出了问题。

Swing API基于布局组件时布局管理器的使用。

相反,您可以创建一个布局管理器,其唯一的职责是履行其管理的组件的位置

AbsoluteLayout

这样做的基本好处是您无需担心调整组件大小,并且它将响应对父容器的更改以及对其周围容器的更改,而无需添加其他侦听器。

您甚至可以在layoutContainer设计边界检查,以确保组件保持在边界内

 import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.LayoutManager2; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class AbsoluteLayoutExample { public static void main(String[] args) { new AbsoluteLayoutExample(); } public AbsoluteLayoutExample() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { public TestPane() { setLayout(new AbsoluateLayoutManager()); JLabel test = new JLabel("Test"); add(test); MouseAdapter ma = new MouseAdapter() { private Point offset; private Component dragComp; @Override public void mousePressed(MouseEvent e) { Point point = e.getPoint(); for (Component comp : getComponents()) { if (comp.getBounds().contains(point)) { offset = new Point(point.x - comp.getX(), point.y - comp.getY()); dragComp = comp; } } } @Override public void mouseReleased(MouseEvent e) { offset = null; dragComp = null; } @Override public void mouseDragged(MouseEvent e) { if (dragComp != null) { Point p = e.getPoint(); Point dragP = new Point(px - offset.x, py - offset.y); dragComp.setLocation(dragP); } } }; addMouseListener(ma); addMouseMotionListener(ma); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } } public class AbsoluateLayoutManager implements LayoutManager2 { @Override public void addLayoutComponent(Component comp, Object constraints) { } @Override public Dimension maximumLayoutSize(Container target) { return preferredLayoutSize(target); } @Override public float getLayoutAlignmentX(Container target) { return 0.5f; } @Override public float getLayoutAlignmentY(Container target) { return 0.5f; } @Override public void invalidateLayout(Container target) { } @Override public void addLayoutComponent(String name, Component comp) { } @Override public void removeLayoutComponent(Component comp) { } @Override public Dimension preferredLayoutSize(Container parent) { int maxX = 0; int maxY = 0; for (Component comp : parent.getComponents()) { Dimension size = comp.getPreferredSize(); maxX = Math.max(comp.getX() + size.width, maxX); maxY = Math.max(comp.getY() + size.height, maxY); } return new Dimension(maxX, maxY); } @Override public Dimension minimumLayoutSize(Container parent) { return preferredLayoutSize(parent); } @Override public void layoutContainer(Container parent) { for (Component comp : parent.getComponents()) { Dimension size = comp.getPreferredSize(); comp.setSize(size); } } } } 

您可能还会考虑类似于此示例的内容 ,这是基于“百分比”的约束来布置组件,因此,它始终位于容器内的给定perctange点