如何防止JLabel位置重置? [英] How to prevent JLabel positions from resetting?

查看:102
本文介绍了如何防止JLabel位置重置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

and the individual labelXMouseDragged methods contain (for example):

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

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

This Panel lives inside another Panel alongside various other controls. I find that I can drag my labels just fine inside the panel (I had my methods correctly checking for bounds, but I have left them like the above for simplicity). However, if the mouse is clicked anywhere that is not a control, either within the inner panel or within the parent panel, the locations of the labels reset. What is causing this to happen? I have no mouseListeners of any kind registered anywhere else, and if I make this panel by itself, I seem to have no issues with clicks.

推荐答案

您可以使用

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.

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

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

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

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.

您甚至可以在layoutContainer中设计边界检查,以确保组件位于边界之内

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

这篇关于如何防止JLabel位置重置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆