Как получить LinearLayout, где компоненты расположены друг над другом в Swing? - PullRequest
2 голосов
/ 17 января 2011

Я пытаюсь создать кастом JDialog. Я хотел бы разместить компоненты друг над другом с их предпочтительной высотой, но ширина должна заполнять контейнер. Аналогично LinearLayout в Android. Я хочу, чтобы компоненты сохраняли предпочтительную высоту при изменении размера окна.

С Использование менеджеров по расположению :

Сценарий: Вам необходимо отобразить несколько компонентов в компактном ряду в их натуральном размере.

Рассмотрите возможность использования JPanel для группировки компонентов и использования менеджера FlowLayout по умолчанию в JPanel или менеджера BoxLayout. SpringLayout также хорош для этого.

например. Я хотел бы иметь JTextField выше JTabbedPane. Я пытался использовать все предложенные менеджеры компоновки FlowLayout, BoxLayout, SpringLayout, но они не сохраняют естественный размер моих компонентов, когда окно JDialog увеличивается по высоте.

Есть ли в Java Swing менеджер компоновки, который я могу использовать в своей ситуации?

Вот небольшой пример, который показывает мою проблему с макетами Swing: A Dialog

import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;

public class TestDialog extends JDialog {

    public TestDialog() {
        setLayout(new BoxLayout(this.getContentPane(), BoxLayout.PAGE_AXIS));
        //setLayout(new SpringLayout());

        JTextField field1 = new JTextField();
        JTextField field2 = new JTextField();
        JTextField field3 = new JTextField();
        JTextField field4 = new JTextField();

        JPanel panel1 = new JPanel();
        JPanel panel2 = new JPanel();

        panel1.setLayout(new BoxLayout(panel1, BoxLayout.PAGE_AXIS));
        panel2.setLayout(new BoxLayout(panel2, BoxLayout.PAGE_AXIS));

        panel1.add(field2);
        panel2.add(field3);
        panel2.add(field4);

        JTabbedPane tabs = new JTabbedPane();
        tabs.addTab("Tab 1", panel1);
        tabs.addTab("Tab 2", panel2);

        add(field1);
        add(tabs);

    //field1.setMaximumSize(field1.getPreferredSize());
    //SpringUtilities.makeCompactGrid(this.getContentPane(), 2, 1, 2, 2, 2, 2);

        this.pack();
        this.setVisible(true);
    }

    public static void main(String[] args) {
        new TestDialog();
    }
}

Ответы [ 6 ]

2 голосов
/ 17 января 2011

Я хотел бы иметь JTextField над JTabbedPane.Я пытался со всеми предлагаемыми менеджерами компоновки

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

textField.setMaximumSize( textField.getPreferredSize() );
tabbedPane.setMaximumSize( tabbedPane.getPreferredSize() );

Если вам нужна дополнительная помощь, опубликуйте SSCCE , который демонстрирует проблему.1011 * Редактировать:

Необходимо указать предпочитаемый размер для текстовых полей.Это делается с помощью:

JTextField textField = new JTextField(10);
1 голос
/ 18 января 2011

В итоге я реализовал собственный StackLayout , код приведен ниже.Вот так выглядит то же приложение в моем вопросе.Компоненты располагаются сверху вниз и занимают всю ширину, аналогично LinearLayout для Android.

My Dialog using StackLayout

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;

public class StackLayout implements LayoutManager {

    @Override
    public void layoutContainer(Container parent) {
        Insets insets = parent.getInsets();
        int maxWidth = parent.getWidth() - (insets.left + insets.right);

        int y = insets.top;

        for(int n = 0; n < parent.getComponentCount(); n++) {
            Component c = parent.getComponent(n);
            int height = c.getPreferredSize().height;
            c.setBounds(0, y, maxWidth, height);

            y += height;
        }
    }

    @Override
    public Dimension minimumLayoutSize(Container c) {
        int sumHeight = 0;
        int maxWidth = 0;

        for(int n = 0; n < c.getComponentCount(); n++) {
            Dimension preferredSize = c.getComponent(n).getPreferredSize();
            if(n == 0) {
                maxWidth = preferredSize.width;
            } else {
                maxWidth += preferredSize.width;
            }
            sumHeight += preferredSize.height;
        }

        // add the containers insets
        Insets insets = c.getInsets();
        sumHeight += insets.top + insets.bottom;
        maxWidth += insets.left + insets.right;

        return new Dimension(maxWidth, sumHeight);
    }

    @Override
    public Dimension preferredLayoutSize(Container c) {
        return minimumLayoutSize(c);
    }

    @Override
    public void addLayoutComponent(String arg0, Component c) {}

    @Override
    public void removeLayoutComponent(Component c) {}

}
1 голос
/ 17 января 2011

Я не совсем понял, что вы имели в виду под естественным размером компонента. Но если вы не хотите, чтобы менеджер компоновки портил размер компонентов, я бы посоветовал вам использовать либо setMaximumSize(int width,int height), либо задать для макета значение null и использовать метод setBounds(int x,int y,int width,int height) для определения размера вашего компонента.

Если вы хотите настроить изменение размеров компонента относительно друг друга, я бы посоветовал взглянуть на GridBagLayout и использовать свойства weightx и weightty.

1 голос
/ 17 января 2011

Нулевой макет (в основном х / у) может быть тем, что вы ищете, или, возможно, групповой макет.

MigLayout также делает то, что вы, вероятно, хотите из коробки (вы должны дать ему специальную директиву для роста с окном, в противном случае это не так).

Концептуально, я думаю, вас смущает тот факт, что макет в конечном итоге определяет размер компонентов, поэтому «естественный» размер немного вводит в заблуждение. Я думаю, что вы после того, как размер установлен на компонент? Или, может быть, вы имеете в виду значение по умолчанию, когда ни один из методов setSize не был вызван для компонента?

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

0 голосов
/ 20 января 2011

Я бы предложил гораздо более простой менеджер компоновки - BorderLayout () - из того, что вы описываете. Код следует: вам нужно указать ширину не менее 1 JTextField, чтобы установить ширину JDialog. Вы можете использовать EmptyBorder, если вы хотите интервалы. Надеюсь, это поможет, - М.С.

import java.awt. *;

import javax.swing. *;

открытый класс TestDialog расширяет JDialog {

private JTextField  field1 = new JTextField(20),
            field2 = new JTextField(),
            field3 = new JTextField(),
            field4 = new JTextField();

public TestDialog(Frame f) {
    super (f, "Test Dialog");
    Container cp = getContentPane();
    cp.setLayout (new BorderLayout());
    cp.add (northPanel(), "North");
    cp.add (tabbedPane(), "Center");
    pack();
}

private JPanel northPanel () {
    JPanel nPanel = new JPanel(new BorderLayout());
    nPanel.add (field1, "Center");
              // nPanel.setBorder (...);
    return nPanel;
}

private JTabbedPane tabbedPane () {
    JTabbedPane tp = new JTabbedPane();
    tp.add ("Tab 1", panel1());
    tp.add ("Tab 2", panel2());
    return tp;
}


private JPanel panel1 () {
    JPanel tfPanel = new JPanel(new BorderLayout());
    tfPanel.add (field2, "North");
    return tfPanel;
}


private JPanel panel2 () {
    JPanel tfPanel = new JPanel(new BorderLayout()),
           t2Panel = new JPanel(new BorderLayout());
    t2Panel.add (field3, "North");
    t2Panel.add (field4, "Center");
    tfPanel.add (t2Panel, "North");
    return tfPanel;
}

public static void main (String[] args) {
    new TestDialog (null).setVisible (true);

}}

0 голосов
/ 17 января 2011

Если вы используете GridBagLayout и не указываете вес или наполнение, вы должны получить то, что хотите.По сути, вы будете иметь 1 столбец 2 ряда сетки сетки.Просто создайте GridBagConstraints и устанавливайте только параметры x и y при добавлении компонентов - не устанавливайте никаких других параметров.

...