Панель GridBagLayout расширяется, игнорируя вертикальный клей BoxLayout

В приведенном ниже примере у меня есть JPanel с BoxLayout, который содержит другую JPanel с GridBagLayout.

Добавляя вертикальный клей, я ожидаю, что содержимое внутренней панели будет «приклеено» к верхней части внешней панели.

Но я вижу метку "А" в центре. Если я удаляю GridBagLayout, вверху отображается A. Почему это происходит?

import javax.swing.*;
import java.awt.*;

public class Test {
    public static void main(String[] args) {
        JPanel contentPane = new JPanel();        

        JFrame frame = new JFrame();
        frame.setContentPane(contentPane);

        contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));

        JPanel gridBagPanel = new JPanel();
        gridBagPanel.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.NONE;

        gridBagPanel.add(new JLabel("A"), gbc);
        contentPane.add(gridBagPanel);
        contentPane.add(Box.createVerticalGlue());

        frame.setSize(800, 200);
        frame.setVisible(true);
    }
}

person ililit    schedule 29.12.2011    source источник


Ответы (3)


Поскольку значение по умолчанию свойства anchor элемента GridBagConstraints равно CENTER. Если на внутренней панели больше места, чем предпочтительный размер JLabel, JLabel будет центрирован по отношению к доступному пространству на внутренней панели (поскольку вы установили для заполнения значение NONE).

Вы можете использовать значение привязки NORTHWEST, чтобы приклеить метку к верхней части панели:

GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weighty = 1;
gbc.weightx = 1;

Вам также необходимо установить веса в соответствии с документацией Java: «Если вы не укажете хотя бы одно ненулевое значение для weightx или weighty, все компоненты слипнутся вместе в центре своего контейнера. Это потому, что, когда вес равен 0,0 (по умолчанию), GridBagLayout помещает дополнительное пространство между сеткой ячеек и краями контейнера."

person Kavka    schedule 29.12.2011
comment
Спасибо, но не помогает с моим примером, A все еще в центре с добавленным выше кодом. - person ililit; 29.12.2011

Вероятно, это связано с тем, что GridBagLayout — это боль в заднице, и вам следует подумать об использовании других менеджеров компоновки. Или может случиться так, что вам нужно установить горизонтальное и вертикальное выравнивание ваших компонентов. Взгляните на setAlignmentX и setAlignmentY документа JComponent. . Всякий раз, когда у меня были компоненты, которые плохо себя вели, это было потому, что я не выровнял все одинаково.

person Paul    schedule 29.12.2011
comment
Спасибо, но добавление JLabel l = new JLabel(A); l.setAlignmentY(Component.TOP_ALIGNMENT); ... не помогло - person ililit; 29.12.2011

Хотя Kavka s' Answer решает требование наличия В верхней части панели с помощью якоря, я считаю, что объявленный вертикальный клей в панели BoxLayout фактически ничего не делает. Итак, я собираюсь расширить это, чтобы внести свой вклад в то, что я понял об использовании весов и вертикального клея в GridBagLayouts.

Поскольку GridBagLayout сложный, причин может быть больше, чем одна, но, как уже указал Кавка:

изменение weightx и weighty от значения по умолчанию 0,0 до ненулевого значения является ключевым.

Как указано в Учебном руководстве по Java по ограничениям GridBag , в разделе описания JavaDoc для GridBagLayout и описание конкретного параметра в JavaDoc для ограничений GridBag.

Если все веса равны нулю, все лишнее пространство появляется между сетками ячейки и

  • для weightx дополнительное пространство появляется между левым и правым краями.
  • для тяжелого дополнительное пространство появляется между верхним и нижним краями.

Итак, если вы хотите использовать вертикальный клей для заполнения пустых ячеек, вам нужно убедиться, что вы придали ненулевой вес компоненту клея в том направлении, в котором вы хотите, чтобы он расширялся. Я собираюсь использовать исключительно GridBagLayout, поэтому параметр gridy позволит мне определить вертикальное распределение компонентов.

Взяв за основу исходный код, мы немного расширили его, чтобы продемонстрировать возможности вертикального склеивания в сочетании с весами. Этот код поместит A на 20% от верхней части панели, сохраняя это соотношение при изменении размера:

import javax.swing.*;
import java.awt.*;

public class Test {
    public static void main(String[] args) {   
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel gridBagPanel = new JPanel();
        gridBagPanel.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        gbc.gridy = 0;
        gbc.weighty = 0.2;
        gridBagPanel.add(Box.createVerticalGlue(), gbc);
        gbc.gridy = 1;
        gbc.weighty = 0;
        gridBagPanel.add(new JLabel("A"), gbc);
        gbc.gridy = 2;
        gbc.weighty = 0.8;
        gridBagPanel.add(Box.createVerticalGlue(), gbc);

        frame.setContentPane(gridBagPanel);
        frame.setSize(800, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

Для получения подробной информации о том, как работает клей, см. Учебное пособие по Java о том, как использовать BoxLayout, раздел «Заполнитель»

person Pau Coma Ramirez    schedule 07.05.2014