【问题标题】:How to prevent JLabel positions from resetting?如何防止 JLabel 位置重置?
【发布时间】:2014-01-21 02:08:47
【问题描述】:

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

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

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

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

此面板与其他各种控件一起存在于另一个面板中。我发现我可以在面板内很好地拖动我的标签(我的方法正确地检查了边界,但为了简单起见,我将它们保留在上面)。但是,如果在非控件的任何地方单击鼠标,无论是在内部面板中还是在父面板中,标签的位置都会重置。是什么导致这种情况发生?我没有在其他任何地方注册任何类型的 mouseListeners,如果我自己制作这个面板,我似乎没有点击问题。

【问题讨论】:

  • 您的面板正在使用一个布局管理器,该管理器正在失效并将标签返回到它认为应该在的位置。答案将取决于您要达到的目标
  • @MadProgrammer - 好吧,我想要实现的是让标签保持在它们被拖动到的位置,以便我以后可以参考它们的位置并保存到数据库(内部面板让某人指定将打印在支票上的各种数据的位置)。即使我将面板完全设为单独的实体,然后将其添加到外部面板,也会出现同样的问题,但将内部面板作为单独的类单独测试不会产生任何问题。
  • “面板”可能在内部无效,也可能因为其父容器发生更改。
  • 当您需要能够随机拖动组件时使用空布局。

标签: java swing jpanel mouseevent jlabel


【解决方案1】:

您可以通过使用null layout 来实现这一点,但我对null 布局有一种病态的厌恶,因为它们有太多的问题。

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

相反,您可以创建一个布局管理器,其唯一职责是尊重它所​​管理的组件的位置

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

您甚至可以在 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 这样的东西,这是一个基于“百分比”的约束来布局组件,因此它们始终位于容器内的给定百分比点

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 2013-01-20
    • 2014-08-25
    • 2010-12-14
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多