Swing GroupLayout: изменение размера и ограничение размеров компонентов

Я использую GroupLayout для управления компонентами в некоторых динамически генерируемых формах ввода данных. Схема примерно такая:

*-----------------------------------------------*
| label A     |   field A                       | 
| label B     |   field B                       |
| label C     |   field C                       |
*-----------------------------------------------*

Я использую 2 параллельные группы для горизонтальной компоновки и одну последовательную группу для вертикальной компоновки. По большей части все работает просто отлично.

Я хочу ограничить максимальную ширину меток (которые являются просто экземплярами JLabel) до 1/3 ширины родительского JFrame. Если бы JFrame был фиксированного размера, это было бы тривиально, но мне приходится иметь дело с его изменением размера.

Я собираю события ComponentListener.componentResized() из JFrame, но я немного застрял в том, что делать, когда я получаю такое событие.

Я пробовал этот подход без везения:

public void componentResized(ComponentEvent e) {
    int maxW = parentFrame.getWidth() / 3;
    for (JLabel l : labels) {
        l.setMaximumSize( // have also tried setSize() and setPreferredSize()
            new Dimension(
                Math.min(l.getSize().width, maxW),
                l.getMaximumSize().height));
    }
    groupLayout.invalidateLayout(getContentSpace());
}

Кто-нибудь может предложить способ ограничения ширины ярлыков, который будет работать?

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


person vaughandroid    schedule 13.12.2011    source источник
comment
никогда не устанавливайтеXXSize: избегайте использования методов setpreferredmaximumminimumsize в java swi"> stackoverflow.com/questions/7229226/   -  person kleopatra    schedule 13.12.2011
comment
Есть ли причина, по которой метка становится больше, чем предпочтительный размер самой большой метки?   -  person trashgod    schedule 13.12.2011
comment
@trashgod Нет, нет. Я хочу установить верхнюю границу ширины меток, а не минимальную границу. Отредактировал вопрос, чтобы сделать это более ясным.   -  person vaughandroid    schedule 14.12.2011


Ответы (1)


В этом примере GroupLayout может просто полагаться на предпочтительный размер метки, не прибегая к какому-либо методу setXXXSize(). В этом подходе

  • Место для этикеток всегда вмещает самую большую этикетку.
  • Размер текстовых полей удобно изменять.
  • Результат правильный для разных платформ и шрифтов.
  • «Вам не нужно ничего указывать для большинства компонентов… потому что сами компоненты имеют желаемое поведение при изменении размера по умолчанию». — Как использовать GroupLayout: размер и изменение размера компонента

Использование GroupLayout.Alignment.TRAILING для выравнивания меток по правому краю является личным предпочтением, и я добавил вторую панель, чтобы показать, как она работает, вложенная в другой макет.

введите здесь описание изображения

import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

/** @see http://stackoverflow.com/questions/8492065 */
public class GroupPanel extends JPanel {

    private JLabel label1 = new JLabel("Primary:");
    private JTextField field1 = new JTextField(16);
    private JLabel label2 = new JLabel("Secondary:");
    private JTextField field2 = new JTextField(16);
    private JLabel label3 = new JLabel("Tertiary:");
    private JTextField field3 = new JTextField(16);

    public GroupPanel(int n) {
        this.setBorder(BorderFactory.createTitledBorder("Panel " + n));
        GroupLayout layout = new GroupLayout(this);          
        this.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        layout.setHorizontalGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                .addComponent(label1)
                .addComponent(label2)
                .addComponent(label3))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(field1)
                .addComponent(field2)
                .addComponent(field3))
        );
        layout.setVerticalGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(label1)
                .addComponent(field1))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(label2)
                .addComponent(field2))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(label3)
                .addComponent(field3))
        );
    }

    private static void display() {
        JFrame f = new JFrame("GroupPanel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS));
        f.add(new GroupPanel(1));
        f.add(new GroupPanel(2));
        f.add(Box.createVerticalGlue());
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                display();
            }
        });
    }
}
person trashgod    schedule 14.12.2011
comment
Это очень яркий пример, так что спасибо за это. Код, который вы предоставили, почти идентичен тому, который я уже реализовал сам, но ключевым моментом было то, что вам не нужно ничего указывать для большинства компонентов… потому что сами компоненты имеют желаемое поведение при изменении размера по умолчанию. Я полагаю, что мои метки должны быть пользовательскими реализациями, которые переопределяют getPreferredSize(). - person vaughandroid; 14.12.2011
comment
Отлично; см. также этот (менее гибкий) пример. - person trashgod; 14.12.2011
comment
См. также этот (более гибкий) пример. - person trashgod; 13.02.2013
comment
У меня прошло пять лет между использованием GroupLayout, поэтому мне пришлось снова обратиться к приведенному выше примеру @trashgod. Это был отличный способ освежить мою память о том, как использовать этот макет. Браво! - person Sheldon R.; 09.01.2017