布局管理器preferredSize Java

6
我仍在努力学习布局管理器的工作原理。我创建了一个带有两个 JPanels 的框架。 第一个包含一个 boxLayout 的 textArea。 第二个包含一个按钮的流式布局。
我根据需要设置了每个面板的 preferredSize,然后打包它们,但结果出乎意料。
import java.awt.*;
import javax.swing.*;

public class LayoutMgrTest
{
    public static void main(String[] args)
    {
        TableBasic frame = new TableBasic();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.setVisible(true);


        frame.getContentPane().setLayout(new GridLayout(2,1));

        JPanel controlPane = new JPanel();
        JPanel buttonPane = new JPanel();

        controlPane.setLayout(new BoxLayout(controlPane, BoxLayout.PAGE_AXIS));
        controlPane.setPreferredSize(new Dimension(200, 200));
        controlPane.add(new JScrollPane(new JTextArea()));

        buttonPane.setLayout(new FlowLayout(FlowLayout.LEFT));
        buttonPane.setPreferredSize(new Dimension(100,20));
        buttonPane.add(new JButton("Button1"));
        buttonPane.add(new JButton("Button2"));

        frame.getContentPane().add(controlPane, BorderLayout.NORTH);
        frame.getContentPane().add(buttonPane, BorderLayout.SOUTH);
        frame.setSize(new Dimension(500,500));
        frame.pack();
    }
}

无论我做什么,如果我使用网格布局,它似乎总是将可用空间的一半分配给每个控件。有人告诉我:
每行的高度取决于添加在每行中的每个组件的高度。
按钮面板的高度为20。 它为其分配了更多空间:
这段代码有什么问题?
请保留两个JPanels不变。直接将文本框和按钮添加到框架很容易,但我需要使用JPanels(因为我将添加边框和其他内容)。
3个回答

7

使用GridLayout作为布局管理器的结果是这样的。将其更改为BorderLayout:

frame.getContentPane().setLayout(new BorderLayout());

例如,这段代码(我尽可能少地更改了原始内容):
import java.awt.*;
import javax.swing.*;

public class LayoutMgrTest
{
    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        //frame.setVisible(true);   
        //frame.getContentPane().setLayout(new BorderLayout());

        JPanel controlPane = new JPanel();
        JPanel buttonPane = new JPanel();

        controlPane.setLayout(new BoxLayout(controlPane, BoxLayout.PAGE_AXIS));
        controlPane.setPreferredSize(new Dimension(200, 200));
        controlPane.add(new JScrollPane(new JTextArea()));

        buttonPane.setLayout(new FlowLayout(FlowLayout.LEFT));
        buttonPane.setPreferredSize(new Dimension(100,40));
        buttonPane.add(new JButton("Button1"));
        buttonPane.add(new JButton("Button2"));

        frame.add(controlPane, BorderLayout.NORTH);
        frame.add(buttonPane, BorderLayout.SOUTH);
        //frame.setSize(new Dimension(500,500));
        frame.pack();
        frame.setVisible(true);
    }
}

生成此框架:

在此输入图片描述


@mKorbel - 谢谢。我的方法总是尽可能少地更改,但我认为你的方法更好 :) - MByD
谢谢你的回答。这次有点晚了,mKorbel :P 通常你总是在Swing GUI方面提供很大的帮助 :) - David
@David,请阅读(@camickr)的加密建议,永远不要将某些东西设置为setSize(),而是使用setBounds()+1。 - mKorbel
请参考如何创建屏幕截图以说明帖子?获取一些制作出色屏幕截图的技巧。 - Andrew Thompson
你在上面的截图中运行哪个操作系统? - Doug Hauf
@Doug - 这个截图来自于 Ubuntu(我想是 11.04 版本)和 GNOME。 - MByD

6

我相应地设置了每个面板的preferredSize。

这是另一个问题。您不应该设置preferred size,这是布局管理器的工作。只需将组件添加到面板中,让布局管理器完成其工作即可。

大多数组件都有默认的preferred size。但对于某些组件,您需要给它一点提示。 例如,当使用文本区域时,您可以通过使用以下代码来给出“建议”的preferred size:

JTextArea textArea = new JTextArea(rows, columns);

好主意,我尽可能会避免使用它。这次我只是在做实验。 - David
不是真的;preferredSize 是布局管理器基于其计算的值之一(虽然不是全部)。它们计算的结果是 size 属性,而不是 preferredSize。 - Michael Borgwardt
3
@Michael,我坚持我的评论。海报不应该设置“controlPane”或“buttonPane”的首选大小。布局管理器将根据添加到它们的组件确定这些面板的首选大小。然后将使用此信息基于添加到框架的所有面板的首选大小来pack()框架。是的,然后布局管理器将设置每个面板的大小/位置。 - camickr
@camickr:嗯,在上下文中你是对的:设置具有布局管理器的容器的首选大小是没有用的;我的陈述对于常规组件是正确的。 - Michael Borgwardt
1
@Michael,即使是独立组件,你也不应该设置大小(最小、最大、首选或实际大小),因为大多数Swing组件都知道如何根据其内容计算自己的最小、首选和最大大小;然后由LayoutMnager负责计算它们的实际大小(和位置)。 - jfpoilpret

3
如果您使用LayoutManager,除了框架之外,请不要在组件上设置大小。
组件的大小是根据不同的布局管理器计算出来的。
您可以在这里找到更多信息。
在您的代码中,您可以将面板与文本区域添加到BorderLayout.CENTER。 这应该解决您的问题。 BorderLayout.CENTER中的组件占据整个空间,除了NORTH,EAST,SOUTH和WEST中所需组件的空间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接