zoukankan      html  css  js  c++  java
  • Swing中支持自动换行的WrapLayout

    原来的WrapLayout有点小bug,会引起抖动,稍微改了一下,现在比较好用了

    package com.miui.theme.tool.gui;
    
    import java.awt.Component;
    import java.awt.Container;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Insets;
    
    import javax.swing.JScrollPane;
    import javax.swing.SwingUtilities;
    
    /**
     * FlowLayout subclass that fully supports wrapping of components.
     */
    public class WrapLayout extends FlowLayout {
        private Dimension preferredLayoutSize;
    
        /**
         * Constructs a new <code>WrapLayout</code> with a left alignment and a
         * default 5-unit horizontal and vertical gap.
         */
        public WrapLayout() {
            super();
        }
    
        /**
         * Constructs a new <code>FlowLayout</code> with the specified alignment and
         * a default 5-unit horizontal and vertical gap. The value of the alignment
         * argument must be one of <code>WrapLayout</code>, <code>WrapLayout</code>,
         * or <code>WrapLayout</code>.
         *
         * @param align
         *            the alignment value
         */
        public WrapLayout(int align) {
            super(align);
        }
    
        /**
         * Creates a new flow layout manager with the indicated alignment and the
         * indicated horizontal and vertical gaps.
         * <p>
         * The value of the alignment argument must be one of
         * <code>WrapLayout</code>, <code>WrapLayout</code>, or
         * <code>WrapLayout</code>.
         *
         * @param align
         *            the alignment value
         * @param hgap
         *            the horizontal gap between components
         * @param vgap
         *            the vertical gap between components
         */
        public WrapLayout(int align, int hgap, int vgap) {
            super(align, hgap, vgap);
        }
    
        /**
         * Returns the preferred dimensions for this layout given the <i>visible</i>
         * components in the specified target container.
         *
         * @param target
         *            the component which needs to be laid out
         * @return the preferred dimensions to lay out the subcomponents of the
         *         specified container
         */
        @Override
        public Dimension preferredLayoutSize(Container target) {
            return layoutSize(target, true);
        }
    
        /**
         * Returns the minimum dimensions needed to layout the <i>visible</i>
         * components contained in the specified target container.
         *
         * @param target
         *            the component which needs to be laid out
         * @return the minimum dimensions to lay out the subcomponents of the
         *         specified container
         */
        @Override
        public Dimension minimumLayoutSize(Container target) {
            Dimension minimum = layoutSize(target, false);
            minimum.width -= (getHgap() + 1);
            return minimum;
        }
    
        /**
         * Returns the minimum or preferred dimension needed to layout the target
         * container.
         *
         * @param target
         *            target to get layout size for
         * @param preferred
         *            should preferred size be calculated
         * @return the dimension to layout the target container
         */
        private Dimension layoutSize(Container target, boolean preferred) {
            synchronized (target.getTreeLock()) {
                // Each row must fit with the width allocated to the containter.
                // When the container width = 0, the preferred width of the
                // container
                // has not yet been calculated so lets ask for the maximum.
                int targetWidth = target.getSize().width;
    
                if (targetWidth == 0)
                    return new Dimension();
    //            if (targetWidth == 0)
    //                targetWidth = Integer.MAX_VALUE;
    
                int hgap = getHgap();
                int vgap = getVgap();
                Insets insets = target.getInsets();
                int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
                int maxWidth = targetWidth - horizontalInsetsAndGap;
    
                // Fit components into the allowed width
    
                Dimension dim = new Dimension(0, 0);
                int rowWidth = 0;
                int rowHeight = 0;
    
                int nmembers = target.getComponentCount();
    
                for (int i = 0; i < nmembers; i++) {
                    Component m = target.getComponent(i);
    
                    if (m.isVisible()) {
                        Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();
    
                        // Can't add the component to current row. Start a new row.
    
                        if (rowWidth + d.width > maxWidth) {
                            addRow(dim, rowWidth, rowHeight);
                            rowWidth = 0;
                            rowHeight = 0;
                        }
    
                        // Add a horizontal gap for all components after the first
    
                        if (rowWidth != 0) {
                            rowWidth += hgap;
                        }
    
                        rowWidth += d.width;
                        rowHeight = Math.max(rowHeight, d.height);
                    }
                }
    
                addRow(dim, rowWidth, rowHeight);
    
                dim.width += horizontalInsetsAndGap;
                dim.height += insets.top + insets.bottom + vgap * 2;
    
                // When using a scroll pane or the DecoratedLookAndFeel we need to
                // make sure the preferred size is less than the size of the
                // target containter so shrinking the container size works
                // correctly. Removing the horizontal gap is an easy way to do this.
    
                Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);
    
                if (scrollPane != null && target.isValid()) {
                    dim.width -= (hgap + 1);
                }
    
                return dim;
            }
        }
    
        /*
         * A new row has been completed. Use the dimensions of this row to update
         * the preferred size for the container.
         *
         * @param dim update the width and height when appropriate
         *
         * @param rowWidth the width of the row to add
         *
         * @param rowHeight the height of the row to add
         */
        private void addRow(Dimension dim, int rowWidth, int rowHeight) {
            dim.width = Math.max(dim.width, rowWidth);
    
            if (dim.height > 0) {
                dim.height += getVgap();
            }
    
            dim.height += rowHeight;
        }
    }
  • 相关阅读:
    ASP.NET MVC 3.0(八): MVC 3.0 传递和保存你的Model
    ASP.NET MVC 3.0(十九): MVC 3.0 实例之使用开源控件实现表格排序和分页
    ASP.NET MVC 3.0(十二): MVC 3.0 使用自定义的Html控件
    ASP.NET MVC 3.0(十七): MVC 3.0 实例之表格中数据的筛选
    ASP.NET MVC 3.0 学习系列
    ASP.NET MVC 3.0(五): 入手Controller/Action
    ASP.NET MVC 3.0(十五): MVC 3.0 实例系列之表格的排序
    ASP.NET MVC 3.0(十): MVC 3.0 使用 Forms身份验证
    ASP.NET MVC 3.0(九): MVC 3.0 验证你的Model
    设计功能与界面的测试
  • 原文地址:https://www.cnblogs.com/TLightSky/p/3482454.html
Copyright © 2011-2022 走看看