如何防止JLabel职位重置?

时间:2014-01-21 02:08:48

标签: java swing jpanel mouseevent jlabel

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

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

并且各个labelXMouseDragged方法包含(例如):

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

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

1 个答案:

答案 0 :(得分:2)

你可以使用null layout来实现这一目标,但我对null布局不满意,但是对它们来说有太多问题。

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(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);
            }
        }

    }

}

您可能还会考虑这样的example这样的基于“百分比”的约束来布置组件,因此总是在容器内的给定的perctange点