You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Swing中WrapLayout窗口快速调整大小时换行异常问题

Swing组件快速调整窗口大小时换行异常问题

运行以下示例代码需依赖MigLayout(Swing版):

public class TestFrame extends JFrame
{

    public TestFrame()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(800, 500));
        JTabbedPane pane = new JTabbedPane();
        pane.addTab("TestFrame", new Panel1());
        add(pane);
        pack();
        setVisible(true);
    }

    /**
     * level-1 panel, also contains other components
     * I just add incorrect panel(Panel2) here
     */
    class Panel1 extends JPanel
    {

        public Panel1()
        {
            MigLayout layout = new MigLayout();
            setLayout(layout);
            add(new Panel2(), new CC().cell(0, 0).growX().pushX());
        }

    }

    /**
     * level-2 panel, also contains other components
     * I just add incorrect panel(CheckBoxesPanel) here
     */
    class Panel2 extends JPanel
    {
        public Panel2()
        {
            MigLayout layout = new MigLayout();
            setLayout(layout);
            add(new CheckBoxesPanel(), new CC().cell(0, 0).growX().pushX());
        }
    }

    class CheckBoxesPanel extends JPanel
    {

        public CheckBoxesPanel()
        {
            WrapLayout layout = new WrapLayout(WrapLayout.LEADING);
            setLayout(layout);
            for (int i = 0; i < 20; i++)
            {
                add(new JCheckBox("JCB" + i));
            }
        }

    }

    public static void main(String[] args)
    {
        new TestFrame();
    }


    class WrapLayout extends FlowLayout
    {

        public WrapLayout()
        {
            super();
        }

        public WrapLayout(int align)
        {
            super(align);
        }

        public WrapLayout(int align, int hGap, int vGap)
        {
            super(align, hGap, vGap);
        }

        @Override
        public Dimension preferredLayoutSize(Container target)
        {
            return layoutSize(target, true);
        }

        @Override
        public Dimension minimumLayoutSize(Container target)
        {
            Dimension minimum = layoutSize(target, false);
            minimum.width -= (getHgap() + 1);
            return minimum;
        }

        private Dimension layoutSize(Container target, boolean preferred)
        {
            synchronized (target.getTreeLock())
            {
                Container container = target;

                while (container.getSize().width == 0 && container.getParent() != null)
                {
                    container = container.getParent();
                }

                int targetWidth = container.getSize().width;
                if (targetWidth == 0)
                {
                    return new Dimension();
                }

                int hGap = getHgap();
                int vGap = getVgap();
                Insets insets = target.getInsets();
                int horizontalInsetsAndGap = insets.left + insets.right + (hGap * 2);
                int maxWidth = targetWidth - horizontalInsetsAndGap;

                Dimension dim = new Dimension(0, 0);
                int rowWidth = 0;
                int rowHeight = 0;

                int count = target.getComponentCount();

                for (int i = 0; i < count; i++)
                {
                    Component m = target.getComponent(i);

                    if (m.isVisible())
                    {
                        Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();

                        if (rowWidth + d.width >= maxWidth)
                        {
                            addRow(dim, rowWidth, rowHeight);
                            rowWidth = 0;
                            rowHeight = 0;
                        }

                        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;

                Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);

                if (scrollPane != null && target.isValid())
                {
                    dim.width -= (hGap + 1);
                }
                return dim;
            }
        }

        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;
        }
    }

}

问题现象

  • 缓慢拖动窗口调整大小时,复选框组件可正常换行,适配窗口宽度
  • 快速拖动窗口时,换行功能异常,复选框无法正确布局,出现错乱

目前推测问题与最小尺寸计算相关,但尚未找到解决办法。


内容的提问来源于stack exchange,提问作者Meltryllis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:40:57