适用于可调整大小的组件的LayoutManager [英] suitable LayoutManager for resizable components

查看:149
本文介绍了适用于可调整大小的组件的LayoutManager的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前段时间我读了这篇文章,其中展示了在Swing中实现鼠标可调整大小的组件的方法。

sometime ago I read this article that shows a way to implement mouse resizable components in Swing.

作者使用null LayoutManager以允许绝对组件定位。
我知道永远不应该使用null布局,所以我的问题是:

The author uses a null LayoutManager in order to allow absolute component positioning. I know that a null layout should never be used, so my question is:

是否有任何已实现的LayoutManager允许组件的绝对定位,或者我有我自己实现它?

is there any already implemented LayoutManager that allow component's absolute positioning, or I have to implement it my own?

推荐答案

布局经理确实做了3件事:

A layout manager really does 3 things:


  1. 设置组件的位置。由于您需要能够拖动组件,因此您不希望布局管理器执行此操作。

  1. Set the location of a component. Since you need the ability to drag the component around, you would not want your layout manager to do this.

设置组件的大小。由于您需要能够调整组件的大小,因此您不希望这样做。但是,您可能希望根据组件首选大小为组件提供默认大小。这样,您无需在创建组件时指定大小。

Set the size of a component. Since you need the ability to resize the component then you would not want to do this. However, you might want to give the component a default size based on the components preferred size. This way you don't need to specify the size when you create the component.

根据添加到其中的组件确定父面板的首选大小。这将允许滚动窗格正常运行,因为可以根据需要添加/删除滚动条。因此,您需要确定拖动应该如何工作的行为。也就是说,您是否允许将组件拖动到面板的当前边界之外。如果是这样,面板的首选尺寸应该会自动增加。

Determine the preferred size of the parent panel based on the components added to it. This will allow scroll panes to function properly as scrollbars can be added/removed as required. So you need to determine the behaviour of how dragging should work. That is, are you allowed to drag the component outside the current bounds of the panel. If so the the preferred size of the panel should automatically increase.




有没有已经实现了允许组件绝对定位的LayoutManager

is there any already implemented LayoutManager that allow component's absolute positioning

我一直在玩一个接近你需要的布局管理器。它旨在与 中的ComponentMover类一起使用。移动Windows 由trashgod提供的链接。

I've been playing around with a layout manager that is close to your needs. It was designed to be used with the ComponentMover class from the Moving Windows link provided by trashgod.

这是我这个类的测试代码:

Here is my test code for this class:

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

/**
 */
public class DragLayout implements LayoutManager, java.io.Serializable
{
    public DragLayout()
    {
    }

    /**
     * Adds the specified component with the specified name to the layout.
     * @param name the name of the component
     * @param comp the component to be added
     */
    @Override
    public void addLayoutComponent(String name, Component comp) {}


    /**
     * Removes the specified component from the layout.
     *
     * @param comp the component to be removed
     */
    @Override
    public void removeLayoutComponent(Component component)
    {
    }

    /**
     *  Determine the minimum size on the Container
     *
     *  @param   target   the container in which to do the layout
     *  @return  the minimum dimensions needed to lay out the
     *           subcomponents of the specified container
     */
    @Override
    public Dimension minimumLayoutSize(Container parent)
    {
        synchronized (parent.getTreeLock())
        {
            return preferredLayoutSize(parent);
        }
    }

    /**
     *  Determine the preferred size on the Container
     *
     *  @param   parent   the container in which to do the layout
     *  @return  the preferred dimensions to lay out the
     *           subcomponents of the specified container
     */
    @Override
    public Dimension preferredLayoutSize(Container parent)
    {
        synchronized (parent.getTreeLock())
        {
            return getLayoutSize(parent);
        }
    }

    /*
     *  The calculation for minimum/preferred size it the same. The only
     *  difference is the need to use the minimum or preferred size of the
     *  component in the calculation.
     *
     *  @param   parent  the container in which to do the layout
     */
    private Dimension getLayoutSize(Container parent)
    {
        Insets parentInsets = parent.getInsets();
        int x = parentInsets.left;
        int y = parentInsets.top;
        int width = 0;
        int height = 0;

        //  Get extreme values of the components on the container

        for (Component component: parent.getComponents())
        {
            if (component.isVisible())
            {
                Point p = component.getLocation();
                Dimension d = component.getPreferredSize();
                x = Math.min(x, p.x);
                y = Math.min(y, p.y);
                width = Math.max(width, p.x + d.width);
                height = Math.max(height, p.y + d.height);
            }
        }

        // Width/Height is adjusted if any component is outside left/top edge

        if (x < parentInsets.left)
            width += parentInsets.left - x;

        if (y < parentInsets.top)
            height += parentInsets.top - y;

        //  Adjust for insets

        width += parentInsets.right;
        height += parentInsets.bottom;
        Dimension d = new Dimension(width, height);

        return d;
//      return new Dimension(width, height);
    }

    /**
     * Lays out the specified container using this layout.
     *
     * @param     target   the container in which to do the layout
     */
    @Override
    public void layoutContainer(Container parent)
    {
    synchronized (parent.getTreeLock())
    {
        Insets parentInsets = parent.getInsets();

        int x = parentInsets.left;
        int y = parentInsets.top;

        //  Get X/Y location outside the bounds of the panel

        for (Component component: parent.getComponents())
        {
            if (component.isVisible())
            {
                Point location = component.getLocation();
                x = Math.min(x, location.x);
                y = Math.min(y, location.y);
            }
        }

        x = (x < parentInsets.left) ? parentInsets.left - x : 0;
        y = (y < parentInsets.top) ? parentInsets.top - y : 0;

        //  Set bounds of each component

        for (Component component: parent.getComponents())
        {
            if (component.isVisible())
            {
                Point p = component.getLocation();
                Dimension d = component.getPreferredSize();

                component.setBounds(p.x + x, p.y + y, d.width, d.height);
            }
        }
    }}

    /**
     * Returns the string representation of this column layout's values.
     * @return   a string representation of this layout
     */
    public String toString()
    {
        return "["
            + getClass().getName()
            + "]";
    }

    public static void main( String[] args )
    {
        ComponentMover cm = new ComponentMover();
        cm.setEdgeInsets( new Insets(-100, -100, -100, -100) );
//      cm.setEdgeInsets( new Insets(10, 10, 10, 10) );
        cm.setAutoLayout(true);

        JPanel panel = new JPanel( new DragLayout() );
        panel.setBorder( new MatteBorder(10, 10, 10, 10, Color.YELLOW) );

        createLabel(cm, panel, "North", 150, 0);
        createLabel(cm, panel, "West", 0, 100);
        createLabel(cm, panel, "East", 300, 100);
        createLabel(cm, panel, "South", 150, 200);
        createLabel(cm, panel, "Center", 150, 100);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new JScrollPane(panel) );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }

    public static void createLabel(ComponentMover cm, JPanel panel, String text, int x, int y)
    {
        JLabel label = new JLabel( text );
        label.setOpaque(true);
        label.setBackground( Color.ORANGE );
        label.setLocation(x, y);
        panel.add( label );
        cm.registerComponent( label );
    }

}




  1. 对于此布局,始终假定大小为首选大小。你需要改变它。当大小为(0,0)时,可能将大小设置为首选大小。在确定父容器的首选大小时,您还需要使用组件的大小(而不是其首选大小)。

  1. For this layout the size is always assumed to be the preferred size. You would need to change this. Maybe set the size to be the preferred size when the size is (0, 0). You will also need to use the size of the component (not its preferred size) when determining the preferred size of the parent container.

ComponentMover类可以是配置为允许您将comopnents拖动到父容器的边界之外,或者将组件保持在边界内。如果允许组件移出边界,则会自动调整首选大小以考虑组件的新位置。

The ComponentMover class can be configured to allow you to drag comopnents outside the bounds of the parent container or to keep the component inside the bounds. If you allow components to be moved outside the bounds, then the preferred size is automatically adjusted to take into account the new location of the component.

如果拖动在顶部或左边界之外的组件,然后所有组件都被移动(向右或向下)确保没有组件具有负位置。

If you drag a component outside the top or left bounds, then all the components are shifted (right or down) do make sure no component has a negative location.

这篇关于适用于可调整大小的组件的LayoutManager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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