Swing:GridLayout 中的级联 JPanel 在调整大小时导致意外间隙

Swing: Cascaded JPanels in GridLayout causes unexpected gap on Resize

我遇到了级联 JPanels 和 GridLayouts 的奇怪行为。

下面的演示展示了我的问题:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class JPanelGridLayoutDemo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("JPanel GridLayout Demo");

        int cols = 5, rows = 5;
        int innerCols = 15, innerRows = 15;

        frame.setLayout(new GridLayout(cols, rows, 0, 0));

        for (int col = 0; col < cols; col++) {
            for (int row = 0; row < rows; row++) {
                JPanel panel = new JPanel();
                panel.setBackground(new Color((int)(Math.random() * 0x1000000)));

                // panel.setLayout(new GridLayout(cols, rows, 0, 0));
                // fixed it as FastSnail suggested
                panel.setLayout(new GridLayout(innerCols, innerRows, 0, 0));
                frame.add(panel);

                for (int innerCol = 0; innerCol < innerCols; innerCol++) {
                    for (int innerRow = 0; innerRow < innerRows; innerRow++) {
                        JPanel innerPanel = new JPanel();
                        innerPanel.setBackground(new Color((int)(Math.random() * 0x1000000)));
                        panel.add(innerPanel);
                    }
                }
            }
        }

        frame.setSize(new Dimension(400, 300));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

    }
}

这将显示以下面板:

我通常不会期望看到外面板的背景颜色。 GridLayout 通常表现为填充父容器。因此,当我将面板水平调整为特定的框架宽度时。然后按预期显示:

我再调整一下,差距又出现了。 frameSize % x == 0 似乎一切都很好,如果这有助于理解问题。

如何解决这个问题,使内部面板始终填满整个父容器?我必须覆盖 GridLayout 吗? 对我来说,这似乎是 GridLayout 的实施问题,例如舍入问题或其他问题。


我按照FastSnail的建议修复了内部GridLayouts,缝隙没有变小但仍然可见:

背景information/Side问题:

我想渲染一个类似于此的可视化效果,首先想到的是像素级渲染。但我想提供悬停、突出显示、点击事件和动态调整大小,因此我在这种情况下使用面板。您认为其中有什么问题吗(性能问题除外)?

我发现 here(FastSnail 建议)GridLayout 由于其内部组件的大小计算而产生间隙。

因此,如果您有一个 100px 宽面板,它包含 15 个面板,其大小将达到 6px (100/15 = 6.67)。结果 10px (100 - 6 * 15) 导致间隙。

因此我将 GridLayout 更改为 MigLayout,现在它按预期工作了:

import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;

import net.miginfocom.swing.MigLayout;

public class JPanelGridLayoutDemo  {

    public static void main(String[] args) {
        JFrame frame = new JFrame("JPanel GridLayout Demo");

        int cols = 5, rows = 5;
        int innerCols = 15, innerRows = 15;

        // fill, remove margin, remove grid gaps
        frame.setLayout(new MigLayout("fill, insets 0, gapx 0, gapy 0"));

        for (int col = 0; col < cols; col++) {
            for (int row = 0; row < rows; row++) {
                JPanel panel = new JPanel();
                panel.setBackground(new Color((int) (Math.random() * 0x1000000)));
                panel.setLayout(new MigLayout("fill, insets 0, gapx 0, gapy 0"));

                // cell position, fill, min-width 1, min-height 1
                frame.add(panel, String.format("cell %d %d, grow, w 1::, h 1::", col, row));

                for (int innerCol = 0; innerCol < innerCols; innerCol++) {
                    for (int innerRow = 0; innerRow < innerRows; innerRow++) {
                        JPanel innerPanel = new JPanel();
                        innerPanel.setBackground(new Color((int) (Math.random() * 0x1000000)));
                        panel.add(innerPanel, String.format("cell %d %d, grow, w 1::, h 1::", innerCol, innerRow));
                    }
                }
            }
        }

        frame.setSize(new Dimension(400, 300));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

    }

}