Swing Draw 1px границы между компонентами в компоненте GridBagLayout - PullRequest
2 голосов
/ 07 апреля 2011

У меня есть компоненты, выложенные в GridBagLayout. Я хочу черную линию в 1 пиксель между всеми компонентами, а также вокруг самой JPanel.

В настоящее время я использую MatteBorder для этого. Родительский компонент имеет 1px MatteBorder на верхнем и левом краях. Каждый дочерний компонент имеет 1px MatteBorder на правом и нижнем краях. Горизонтальные и вертикальные промежутки равны нулю на GridBagLayout.

Это в основном работает, за исключением того, что я получаю случайные промежутки, когда дочерние границы встречаются с родительскими границами. Gaps in borders

Я подозреваю, что это связано с неточностью округления / с плавающей запятой в распределении дополнительного пространства для дочерних компонентов.

Есть ли лучший способ добиться этого вида?

В приложении приведен более простой пример:

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
}

Что выглядит так:

enter image description here

1 Ответ

2 голосов
/ 07 апреля 2011

Думаю, я бы использовал BorderFactory.createLineBorder(color, thickness) вместо ... matteBorder, поскольку LineBorder кажется немного ближе к тому, что вы хотите сделать. Для удобства вы также можете использовать LineBorder.createBlackLineBorder().

Если внешние стороны некоторых компонентов не попадают внутрь своих контейнеров, убедитесь, что в контейнерах (т.е. внешних компонентах) не установлены ненулевые вставки!


Альтернативное решение может состоять в том, чтобы ваш фоновый контейнер имел черный фон и вставки в 1 пиксель, и размещал на нем компоненты без границ с промежутками в 1 пиксель между ними. Это должно приводить к очень точным черным линиям везде, где у вас нет компонента сверху, а также устраняет проблему, когда множественные границы встречаются друг с другом и в результате получается граница двойной ширины.


Наконец, мне кажется, что вы используете компоненты для рисования таблиц. Вам нужны эти компоненты, чтобы иметь какое-то поведение, или было бы хорошо, если бы вы просто помещали таблицы в ваши компоненты? Вы можете сделать это довольно удобно, например, используя JLabel s JTextPanel s и настройку их свойств text в HTML для всего, что вы хотите отобразить. Java включает в себя довольно сложный механизм макета HTML, который даже обрабатывает хорошее подмножество CSS, либо встроенное, либо даже из файла href.

...