【问题标题】:Swing Draw 1px border lines between components in a GridBagLayout componentSwing 在一个 GridBagLayout 组件中的组件之间绘制 1px 的边框线
【发布时间】:2011-04-07 19:33:41
【问题描述】:

我在 GridBagLayout 中布置了组件。我想要在所有组件之间以及 JPanel 本身周围有一条 1px 的黑线。

目前,我正在使用 MatteBorder 来执行此操作。父组件的顶部和左侧边缘有一个 1px MatteBorder。每个子组件的右下边缘都有一个 1px MatteBorder。 GridBagLayout 上的水平和垂直间隙为零。

这主要是有效的,除了我偶尔会在子边界与父边界相遇的地方出现间隙。

我怀疑这是由于向子组件分配额外空间时舍入/浮点数不准确造成的。

有没有更好的方法来实现这种外观?

附上一个更简单的例子:

public class SSBGuiTest extends JDialog {
    public SSBGuiTest(Frame owner) {
        super(owner);
        initComponents();
    }

    public SSBGuiTest(Dialog owner) {
        super(owner);
        initComponents();
    }

    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents
        wrapperPanel = new JPanel();
        panelWithTopLeftMatteBorder = new JPanel();
        panel1 = new JPanel();
        label1 = new JLabel();
        panel2 = new JPanel();
        label2 = new JLabel();
        panel3 = new JPanel();
        label3 = new JLabel();

        //======== this ========
        Container contentPane = getContentPane();
        contentPane.setLayout(new BorderLayout());

        //======== wrapperPanel ========
        {
            wrapperPanel.setBorder(new EmptyBorder(15, 15, 15, 15));
            wrapperPanel.setLayout(new BorderLayout());

            //======== panelWithTopLeftMatteBorder ========
            {
                panelWithTopLeftMatteBorder.setBorder(new MatteBorder(1, 1, 0, 0, Color.black));
                panelWithTopLeftMatteBorder.setLayout(new GridBagLayout());
                ((GridBagLayout)panelWithTopLeftMatteBorder.getLayout()).columnWidths = new int[] {0, 0};
                ((GridBagLayout)panelWithTopLeftMatteBorder.getLayout()).rowHeights = new int[] {0, 0, 0, 0};
                ((GridBagLayout)panelWithTopLeftMatteBorder.getLayout()).columnWeights = new double[] {1.0, 1.0E-4};
                ((GridBagLayout)panelWithTopLeftMatteBorder.getLayout()).rowWeights = new double[] {1.0, 1.0, 1.0, 1.0E-4};

                //======== panel1 ========
                {
                    panel1.setBorder(new MatteBorder(0, 0, 1, 1, Color.black));
                    panel1.setLayout(new BorderLayout());

                    //---- label1 ----
                    label1.setHorizontalAlignment(SwingConstants.CENTER);
                    label1.setText("label1");
                    panel1.add(label1, BorderLayout.CENTER);
                }
                panelWithTopLeftMatteBorder.add(panel1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                    new Insets(0, 0, 0, 0), 0, 0));

                //======== panel2 ========
                {
                    panel2.setBorder(new MatteBorder(0, 0, 1, 1, Color.black));
                    panel2.setLayout(new BorderLayout());

                    //---- label2 ----
                    label2.setHorizontalAlignment(SwingConstants.CENTER);
                    label2.setText("label2");
                    panel2.add(label2, BorderLayout.CENTER);
                }
                panelWithTopLeftMatteBorder.add(panel2, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                    new Insets(0, 0, 0, 0), 0, 0));

                //======== panel3 ========
                {
                    panel3.setBorder(new MatteBorder(0, 0, 1, 1, Color.black));
                    panel3.setLayout(new BorderLayout());

                    //---- label3 ----
                    label3.setHorizontalAlignment(SwingConstants.CENTER);
                    label3.setText("label3");
                    panel3.add(label3, BorderLayout.CENTER);
                }
                panelWithTopLeftMatteBorder.add(panel3, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0,
                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                    new Insets(0, 0, 0, 0), 0, 0));
            }
            wrapperPanel.add(panelWithTopLeftMatteBorder, BorderLayout.CENTER);
        }
        contentPane.add(wrapperPanel, BorderLayout.CENTER);
        pack();
        setLocationRelativeTo(getOwner());
        // JFormDesigner - End of component initialization  //GEN-END:initComponents
    }

    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables
    private JPanel wrapperPanel;
    private JPanel panelWithTopLeftMatteBorder;
    private JPanel panel1;
    private JLabel label1;
    private JPanel panel2;
    private JLabel label2;
    private JPanel panel3;
    private JLabel label3;
    // JFormDesigner - End of variables declaration  //GEN-END:variables
}

看起来像这样:

【问题讨论】:

    标签: java swing layout border


    【解决方案1】:

    我想我会使用 BorderFactory.createLineBorder(color, thickness) 而不是 ...matteBorder,因为 LineBorder 似乎更接近您想要做的事情。为方便起见,您还可以使用LineBorder.createBlackLineBorder()

    如果某些组件的外部没有完全接触到它们的容器内部,请检查容器(即外部组件)是否没有设置非零插图!


    另一种解决方案可能是让您的背景容器具有黑色背景和 1 个像素的插图,并在其上放置无边框的组件,它们之间有 1 个像素的间隙。这应该会在您顶部没有组件的任何地方产生非常精确的黑线,并且还消除了多个边框相遇并导致双宽边框的问题。


    最后,在我看来,您正在使用组件来绘制表格。您是否需要这些组件具有某种行为,或者只在组件上放置表格就可以了?你可以很方便地使用例如JLabels JTextPanels 并将它们的 text 属性设置为 HTML 以显示您想要显示的任何内容。 Java 包含一个相当复杂的 HTML 布局引擎,它甚至可以处理 CSS 的一个很好的子集,无论是内联的还是来自 href'd 文件的。

    【讨论】:

    • Carl,我正在尝试获得精确的边界。如果两个带有线边框的组件相互对接,那里将有一个 2px 的边框而不是 1px。
    • 我确实尝试了黑色背景,1px 填充,白色组件覆盖,但出于某种原因,顶部和底部子组件的顶部和底部边框较粗。另外,我正在从该组件生成 PDF,并且担心黑色背景可能不如实际线坐标最佳 PDF 指令。
    • @Sam Barnum:感谢您的澄清!我还没有完全解决你的问题,但我已经能够重现它。通过在各个面板上设置不同的背景颜色,我能够表明您的内部组件没有完全填充外部面板:顶部、右侧和底部有 2px 的间隙。也许有你不知道或没有看过的插图?
    • @Sam Barnum:您的解决方案几乎有效,所以我不敢质疑它,但为什么要使用迂回的方式生成 PDF?您可以使用 XML 工具和 Xalan-FO 等非常轻松地生成那种图片……是否真的需要将这些东西作为实际组件显示在屏幕上?
    • @Carl,PDF 生成是次要的,其中大部分是针对复杂的 Swing 应用程序。该应用程序的一项功能是生成屏幕上内容的 PDF 表示。我认为没有任何隐藏的插图,它们都在示例的代码中。我认为如果组件设置为增长,GridBagLayout 可能就不是那么准确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 2013-01-28
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多