Проблема Swing BoxLayout - Не удается заставить Наполнители делать свою работу - PullRequest
7 голосов
/ 29 июня 2011

Что я пытаюсь сделать

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

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


Что я пробовал

Поэтому я попытался использовать fillers в BoxLayout, как объяснено в Использование невидимых компонентов в качестве наполнителя , но он просто не работает. Хотя в документации Oracle, это было именно то, что мне нужно. Вот мои попытки:

    import javax.swing.Box;
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;


    public class TestBoxLayout implements Runnable {

        public static void main(String[] args) {
            SwingUtilities.invokeLater(new TestBoxLayout());
        }

        @Override
        public void run() {
            JFrame f = new JFrame("test box layout");

            JPanel b = new JPanel();
            b.setLayout(new BoxLayout(b, BoxLayout.PAGE_AXIS));

            b.add(new JTextField("field 1"));
            b.add(new JTextField("field 2"));
            b.add(new JTextField("field 3"));
            b.add(Box.createVerticalGlue());

            f.setContentPane(b);
            f.setSize(500, 200);
            f.setVisible(true);
        }

    }

Вот результат, который я получаю:

Fillers are not working


Вторая попытка

Я пытался использовать класс Box вместо JPanel с BoxLayout, но визуальный результат точно такой же. Вот моя вторая попытка:

    import javax.swing.Box;
    import javax.swing.JFrame;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;


    public class TestBox implements Runnable {

        public static void main(String[] args) {
            SwingUtilities.invokeLater(new TestBox());
        }

        @Override
        public void run() {
            JFrame f = new JFrame("test box");

            Box b = Box.createVerticalBox();

            b.add(new JTextField("field 1"));
            b.add(new JTextField("field 2"));
            b.add(new JTextField("field 3"));
            b.add(Box.createVerticalGlue());

            f.setContentPane(b);
            f.setSize(500, 200);
            f.setVisible(true);
        }

    }

Что бы я хотел сделать

Кто-нибудь знает, как я могу исправить эти наполнители и заставить их работать? Исправление в данном коде было бы фантастическим.

Это рисунок, который я сделал с использованием краски, который показывает, что я хотел бы получить в результате: Expected result

Ответы [ 3 ]

2 голосов
/ 29 июня 2011

BoxLayout отлично подходит для того, что вы пытаетесь сделать. Клей вставки как последний компонент в порядке. Почему вы просто не используете методы setMaximumSize в ваших JTextFields? Я не уверен, что один JTextFields может удовлетворить ваши потребности. Если использование setMaximumSize не работает, поместите каждый JTextField в JPanel, а затем используйте setMaximumSize для каждого JPanel.

1 голос
/ 06 августа 2012

ОП спросил, как он может заставить BoxLayout уважать вертикальный клей только с JTextField с. Максимальная высота текстового поля может быть установлена ​​от getPreferredSize().

Однако в моем случае мне также нужно JTextArea, и ситуация становится более странной: JTextArea и вертикальный клей, кажется, разделяют оставшуюся высоту вместе, хотя я ограничил максимальную высоту JTextArea.

Приведенный ниже код исправляет проблему OP с JTextField s, но проблема с JTextArea остается (когда вы раскомментируете закомментированную часть, вы увидите некоторое «забавное» поведение).

import java.awt.Dimension;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class TestBox implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TestBox());
    }

    @Override
    public void run() {
        JFrame f = new JFrame("test box");

        Box b = Box.createVerticalBox();

        JTextField field1 = new JTextField();
        JTextField field2 = new JTextField();
        field1.setMaximumSize(new Dimension(Integer.MAX_VALUE, field1.getPreferredSize().height));
        field2.setMaximumSize(new Dimension(Integer.MAX_VALUE, field2.getPreferredSize().height));
        b.add(field1);
        b.add(field2);

//        JTextArea area = new JTextArea();
//        area.setRows(4);
//        area.setMaximumSize(new Dimension(Integer.MAX_VALUE, area.getPreferredSize().height));
//        b.add(new JScrollPane(area));

        b.add(Box.createVerticalGlue());

        f.setContentPane(b);
        f.setSize(500, 200);
        f.setVisible(true);
    }
}
0 голосов
/ 04 сентября 2014

Многие посты осуждают недостатки Box с размером клея и выравниванием контента.Эти проблемы возникают из-за использования BoxLayout методов SizeRequirements calcTiledPositions и CalculateAlignedPositions.Эти методы изящно кратки, но настолько упрощены, что результаты часто не соответствуют ожидаемому поведению.

Обходной путь для исходного вопроса - установить большое значение для предпочтительного размера клея:

    Box.Filler glue = (Box.Filler) Box.createVerticalGlue();
    glue.changeShape(glue.getMinimumSize(), 
           new Dimension(0, Short.MAX_VALUE),   // prefer it big
           glue.getMaximumSize());
    b.add(glue);

Это работает для трех JTextFields, но не при добавлении прокручиваемой JTextArea.Более общее решение состоит в том, чтобы установить LayoutManager Box в подкласс BoxLayout, который переписывает layoutContainer ().Замените вызовы вышеуказанных методов кодом, который лучше соответствует вашим потребностям.

...