如何在Swing中获得一个LinearLayout,其中组件堆叠在彼此的顶部?

时间:2011-01-17 16:06:31

标签: java swing layout android-linearlayout layout-manager

我正在尝试创建自定义JDialog。我希望将组件堆叠在彼此顶部并具有其首选高度,但宽度应该填充容器。与Android中的LinearLayout类似。我希望组件在调整窗口大小时保持其首选高度。

来自Using Layout Managers

  

场景:您需要在自然尺寸的紧凑行中显示一些组件。

     

考虑使用JPanel对组件进行分组,并使用JPanel的默认FlowLayout管理器或BoxLayout管理器。 SpringLayout对此也有好处。

E.g。我希望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 个答案:

答案 0 :(得分:2)

  

我想在JTabbedPane上面有一个JTextField。我尝试了所有建议的布局管理器

垂直BoxLayout应该可以正常工作。如果在增加帧大小时组件增长,则可能需要添加:

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

如果您需要更多帮助,请发布展示问题的SSCCE

编辑:

您需要为文本字段指定首选大小。这可以通过使用:

完成
JTextField textField = new JTextField(10);

答案 1 :(得分:1)

null布局(基本上是x / y)可能是你要找的,或者可能是Group Layout。

MigLayout也可以开箱即用你想要的东西(你必须给它一个特定的指令来与窗口一起成长,否则它不会。)

从概念上讲,我认为您对布局最终决定组件大小的事实感到困惑,因此“自然”大小有点误导。我想你所追求的是组件上设置的大小?或者,如果没有在组件上调用任何setSize方法,那么你的意思是默认值?

无论哪种方式,使用Swing,您必须更明确地确定您的尺寸预期,以获得良好的效果。

答案 2 :(得分:1)

我完全没理解你的自然组件的大小。但是如果您不希望布局管理器弄乱组件的大小,我建议您使用setMaximumSize(int width,int height)或将布局设置为null并使用setBounds(int x,int y,int width,int height)方法来调整组件的大小。

如果您想调整组件的大小相对于彼此的变化,那么我建议您查看GridBagLayout并使用weightx和weighty属性。

答案 3 :(得分:1)

我最终实现了自己的 StackLayout ,代码如下。这就是我的问题中的相同应用程序的样子。这些组件从顶部到底部堆叠,占据整个宽度,类似于Android的LinearLayout

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) {}

}

答案 4 :(得分:0)

如果你使用GridBagLayout并且没有指定填充或重量,你应该得到你想要的。基本上你将有一个2列2行网格袋布局。只需创建GridBagConstraints并在添加组件时仅设置x和y选项 - 不要设置任何其他选项。

答案 5 :(得分:0)

我会建议一个更简单的布局管理器 - BorderLayout() - 来自你所描述的内容。代码如下:您需要指定至少1个JTextField的宽度来设置JDialog的宽度。如果需要一些间距,可以使用EmptyBorder。希望这会有所帮助, - M.S。

import java.awt。*;

导入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);

}}