2

我正在尝试创建一个自定义JDialog. 我想让组件以它们的首选高度堆叠在一起,但宽度应该填满容器。类似于LinearLayout在安卓中。我希望在调整窗口大小时组件保持其首选高度。

使用布局管理器

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

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

例如,我想要一个JTextField以上的JTabbedPane. 我已尝试使用所有建议的布局管理器 FlowLayout、BoxLayout、SpringLayout,但当JDialog窗口高度增加时,它们不会保留我的组件的自然大小。

Java Swing 中是否有任何布局管理器可以用于我的情况?

这是一个小例子,展示了我对 Swing 布局的问题: 一个对话框

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();
    }
}
4

6 回答 6

2

我想在 JTabbedPane 上方有一个 JTextField。我已经尝试过所有建议的布局管理器

垂直 BoxLayout 应该可以正常工作。如果增加框架大小时组件增长,那么您可能需要添加:

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

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

编辑:

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

JTextField textField = new JTextField(10);
于 2011-01-17T16:31:37.513 回答
1

空布局(基本上是 x/y)可能是您正在寻找的,或者可能是组布局。

MigLayout 还可以做你可能想要的开箱即用(你必须给它一个特定的指令以随窗口增长,否则它不会)。

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

无论哪种方式,对于 Swing,您都必须更明确地确定您的大小预期,才能获得良好的结果。

于 2011-01-17T16:18:03.297 回答
1

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

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

于 2011-01-17T17:37:43.220 回答
1

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

我的对话框使用 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) {}

}
于 2011-01-18T12:28:00.320 回答
0

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

于 2011-01-17T17:38:10.380 回答
0

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

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

}}

于 2011-01-20T05:44:40.227 回答