Центрирование макета блока после удаления компонентов

У меня есть программа, которая создает JButtons, которые затем добавляются в JPanel с BoxLayout, который настроен на их вертикальное размещение. Иногда первая кнопка намеренно удаляется из JPanel. Первоначально кнопки центрированы правильно, и кнопки также успешно удаляются. Проблема в том, что оставшиеся кнопки затем раздвигаются, чтобы заполнить пространство. Это не то, что я хотел бы, вместо этого я хотел бы, чтобы они повторно центрировались по оси Y, не раздвигаясь.

У меня есть класс, который расширяет JPanel. В конструкторе создается BoxLayout.

setPreferredSize(new Dimension(150, 500));
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setAlignmentY(CENTER_ALIGNMENT);

Создание кнопок в настоящее время является методом в этом классе:

createButtons(int numButtons){
for (int i=0;i<numButtons;i++) {
    add(new JButton());
}

И удаление - еще один метод:

removeButton(){
    if(getComponentCount()>1){
        remove(0);
        validate();
        repaint();
    }
}

Кто-нибудь знает, как сделать, чтобы кнопки оставались центрированными вдоль оси Y, не расширяясь, чтобы заполнить содержащую панель?


person Invincibloobles    schedule 02.07.2012    source источник
comment
Чтобы быстрее получить помощь, опубликуйте SSCCE.   -  person Andrew Thompson    schedule 02.07.2012
comment
Кстати, почему этот код имеет атрибут с именем getComponentCount? Я бы ожидал componentCount или getComponentCount().   -  person Andrew Thompson    schedule 02.07.2012
comment
предполагается, что это getComponentCount(), это была опечатка при написании вопроса! Плохо, сейчас поменяю. Спасибо, что указали на это.   -  person Invincibloobles    schedule 02.07.2012
comment
сейчас изменит Нет, не редактируйте вручную. Всегда копируйте/вставляйте код, HTML/XML или ввод/вывод. И пока вы это делаете, публикуйте SSCCE, а не фрагменты кода. После рассмотрения нескольких других вопросов , я как раз пытался превратить эти фрагменты в компилируемый код, когда заметил странное имя «атрибута».   -  person Andrew Thompson    schedule 02.07.2012


Ответы (3)


Слышали ли вы о клее в BoxLayouts, который использует невидимый компонент в качестве наполнителя (клея), который, я думаю, должен помочь удерживать кнопки в центре, см. эти 2 ссылки: документы BoxLayout и BoxLayout - Filler на этом сайте также есть отличный учебник по Boxlayout с клеем: BoxLayout Glue и это

person David Kroukamp    schedule 02.07.2012
comment
Я слышал об этом, но не был уверен, как это работает. Я только что попробовал добавить клей до и после цикла for, который создает кнопки, и все кнопки исчезли. Не слишком уверен, почему это произошло. Вы знаете, считается ли клей компонентом? Итак, если я сначала добавлю клей, а затем удалю (0), удалит ли он клей? - person Invincibloobles; 02.07.2012
comment
@Invincibloobles да, насколько я знаю, это невидимый компонент - person David Kroukamp; 02.07.2012
comment
Итак, я добавил клей до и после цикла создания кнопок, и теперь кнопки появляются. Я изменил remove, так что теперь он делает remove(1) вместо 0, так что он не удаляет клей. Но он все еще не работает. Кнопки все равно расходятся - person Invincibloobles; 02.07.2012
comment
@Invincibloobles за помощью скорее опубликуйте sscce.org, который представляет собой небольшой пример, который можно скомпилировать из простой копии и вставьте и проиллюстрируйте вашу проблему, это поможет мне протестировать ваш код и оказать вам соответствующую помощь! - person David Kroukamp; 02.07.2012
comment
На какое-то время потерял подключение к Интернету, поэтому только что видел некоторые из этих ответов, но, в конце концов, я заставил его работать с клеем, чтобы центрировать кнопки, а затем с несколькими стойками, чтобы раздвинуть их на небольшое расстояние (4 или 5 пикселей или около того) - person Invincibloobles; 02.07.2012
comment
@Invincibloobles по крайней мере работает :). Вот что имеет значение (и, конечно, то, что вы узнали что-то новое) - person David Kroukamp; 02.07.2012

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

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TestButtons {

    protected void createAndShowGUI() {
        JFrame frame = new JFrame("Test buttons/BoxLayout");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createLineBorder(Color.RED));
        // panel.setPreferredSize(new Dimension(150, 500));
        BoxLayout mgr = new BoxLayout(panel, BoxLayout.Y_AXIS);
        panel.setLayout(mgr);
        for (int i = 0; i < 5; i++) {
            final JButton button = new JButton("Remove Hello World " + (i + 1));
            button.setAlignmentX(Component.CENTER_ALIGNMENT);
            button.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    panel.remove(button);
                    panel.revalidate();
                    panel.repaint();
                }
            });
            panel.add(button);
        }
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestButtons().createAndShowGUI();
            }
        });
    }

}
person Guillaume Polet    schedule 02.07.2012

Я считаю, что это проблема с использованием BOX Layout. Кнопки остаются в центре, но «заполняют» края панели, в которую они добавлены. Я считаю, что правильный способ сделать это (если вы знаете количество кнопок, которые вы собираетесь создать) — использовать макет сетки с методом setPreferedSize.

JButton btn = new JButton(String.valueOf(i));
btn.setPreferredSize(new Dimension(40, 40));
panel.add(btn);
person Matt Westlake    schedule 02.07.2012
comment
Да, я верю, что вы можете быть правы. Проблема в том, что он также полностью игнорирует команду setPreferedSize() и по-прежнему работает так же. Есть ли альтернативный макет, который можно было бы использовать вместо этого? - person Invincibloobles; 02.07.2012
comment
Макет сетки будет работать, но вы должны знать столбцы и строки при создании панели. вы всегда можете добавить дополнительные строки, но количество столбцов должно быть правильным. Он просто не заполнит дополнительные строки, если вы не используете их все. Кроме того, в сообщении ниже моего предлагается клей в BoxLayouts, с которым я не знаком, но вы можете подумать об этом. - person Matt Westlake; 02.07.2012
comment
Не форсируйте предпочтительный размер компонентов (если только вы не выполняете их отрисовку/рендеринг). Jbutton зависит от L и F, поэтому 40x40 может быть слишком большим в некоторых случаях и слишком маленьким в некоторых других. - person Guillaume Polet; 02.07.2012
comment
Только сторона BoxLayout поддерживает метод setPreferredSize() (менеджеры компоновки могут принимать или игнорировать методы setMaximumSize(), setMinimumSize() и setPreferredSize()). BoxLayout принимает во внимание максимальный и минимальный размер, но для PreferredSize это зависит от направления макета: X_AXIS — учитывает предпочтительную ширину, а Y_AXIS — учитывает предпочтительную высоту. - person Michael; 02.07.2012