How to prevent JLabel positions from resetting?

后端 未结 1 738
一整个雨季
一整个雨季 2020-12-20 10:07

I have a JPanel that contains 11 JLabels, each of them registered with a MouseMotionListener like so (generated by Netbeans):

label1.addMouseMotionListener(n         


        
相关标签:
1条回答
  • 2020-12-20 10:26

    You could achieve this by using a null layout, but I have a pathalogical dislike for null layouts, too many things go wrong with them.

    The Swing API is based around the use of layout managers when laying out components.

    Instead, you could create a layout manager whose sole responsibility would be to honour the position of the components it is managing

    AbsoluteLayout

    The basic benefit of this is you don't need to worry about sizing the components and that it will respond to changes to the parent container as well as changes to the containers around it without you needing to add additional listeners.

    You could even devise a bounds check within the layoutContainer to ensure that the components stay within bounds

    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(p.x - offset.x, p.y - 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);
                }
            }
    
        }
    
    }
    

    You might also consider something like this example which is a "percentage" based constraint to lay out components, so thay are always at a given perctange point within the container

    0 讨论(0)
提交回复
热议问题