自定义可拖动布局管理器

时间:2014-06-30 09:18:56

标签: java swing layout layout-manager

我正在实现一个小部件板来控制许多小部件(扩展JComponents),这些小部件必须实现几个特性:可调整大小,可拖动,可关闭等...

我想到了空(或绝对)布局,因为所有其他本机布局管理器都不支持所需的功能(拖动组件并将其放在特定位置)。但众所周知,使用绝对经理甚至不推荐,但在Netbeans RCP中也是禁止的。所以我试图实现我自己的布局管理器,它尽可能接近绝对布局并提供一些额外的功能。

这是我的布局原型的代码

public class WidgetLayout implements LayoutManager, java.io.Serializable {

    private boolean usePreferredSize;

    /**
     * Convenience constructor
     */
    public WidgetLayout() {
        this(true);
    }

    /**
     * Create a DragLayout and indicate how the component size is determined.
     *
     * @param usePreferred size see setPreferredSize() for values.
     */
    public WidgetLayout(boolean usePreferredSize) {
        setUsePreferredSize(usePreferredSize);
    }

    /**
     * Set the use preferred size property
     *
     * @param usePreferredSize when true, use the preferred size of the
     * component in layout calculations. When false, use the size of the
     * component, unless the size is 0, in which case use the preferred size as
     * a default.
     */
    public void setUsePreferredSize(boolean usePreferredSize) {
        this.usePreferredSize = usePreferredSize;
    }

    /**
     * Get the use Preferred Size property
     *
     * @return the use preferred size property
     */
    public boolean isUsePreferredSize() {
        return usePreferredSize;
    }

    /**
     * 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 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);
        }
    }

    /**
     * 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);
        }
    }

    /**
     * Lays out the specified container using this layout.
     *
     * @param   target the container in which to do the layout
     */
    @Override
    public void layoutContainer(Container parent) {
    }

    /*
     *  The calculation for minimum/preferred size is the same.
     *
     *  @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.
        //  The x/y values represent the starting point relative to the
        //  top/left of the container. The width/height values represent
        //  the bottom/right value within the container.
        for (Component component : parent.getComponents()) {
            if (component.isVisible()) {
                Point p = component.getLocation();
                Dimension d = component.getSize();
                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);
            }
        }

        Dimension d = new Dimension(width, height);

        return d;

    }

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

}

它有点工作,但是我的RCP应用程序中的其他组件出现了问题。

在TopComponent中有一个带有此布局的JPanel。 return parent.getParent().getParent().getSize();确保此面板与topComponent本身具有相同的大小(它是唯一的组件,它可用作画布或板)。但是,当我想增加资源管理器的大小时,例如,我不能。我只能用更大的布局来制作电路板,但不能更小。我想我知道原因(我的布局面板设置了尽可能高的首选尺寸),但我不知道如何纠正这个问题。有什么提示吗?

编辑:我需要的是这个布局与TopComponent的大小相同,但TopComponent应该能够增加和减小它的大小...

EDIT2:问题解决了。我基于DragLayout上的一些函数,现在它表现为AbsoluteLayout,但是当它的大小改变时不会移动其他组件(除非它上面的整个组件改变大小) - 参见上面的代码。

另外,诀窍是将实现此布局的组件置于某个布局中,该布局不会在容器的中间强制新创建的组件,因此我将其放入GridLayout(1, 1),填充整个组件默认情况下: - )

1 个答案:

答案 0 :(得分:0)

解决了 - 请参阅编辑问题。我将在这里留下问题,也许有人可以在实现类似绝对布局的布局管理器时使用它......