gpt4 book ai didi

java - swing flowlayout preferredSize 不会自动改变

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:23:39 25 4
gpt4 key购买 nike

我想为 MyPanel 添加一个 FlowLayout 来添加一些任意按钮。我将 MyPanel 添加到 JFrame north(JFrame 有一个 BorderLayout)。我的问题是:
MyPanel中的按钮超过一行时,不显示。
换句话说,MyPanelpreferredSize 不会自动更改以显示其全部内容。它只显示一排按钮。

 public class NewMain {
public static void main(String[] args) {
JFrame mainFrame = new JFrame();
mainFrame.getContentPane().setLayout(new BorderLayout());
mainFrame.setSize(new Dimension(500,500));

JPanel p1 = new MyPanel();
p1.setLayout(new FlowLayout());
mainFrame.add(p1,BorderLayout.NORTH);
mainFrame.add(new JButton("center"),BorderLayout.CENTER);
p1.add(new JButton("helllloo1"));
p1.add(new JButton("helllloo2"));
p1.add(new JButton("helllloo3"));
p1.add(new JButton("helllloo4"));
p1.add(new JButton("helllloo5"));
p1.add(new JButton("helllloo6"));
p1.add(new JButton("helllloo7"));

mainFrame.setVisible(true);
}

public static class MyPanel extends JPanel{

}
}

enter image description here

当我更改 MyPanel 使其覆盖 getPreferredSize 并设置常量大小时,它可以正常工作。

public static class MyPanel extends JPanel{

@Override
public Dimension getPreferredSize(){
return new Dimension(-1,100);
}
}

enter image description here

但我希望它自动工作。
任何帮助将不胜感激。

最佳答案

布局管理器有两个主要功能:

  • 确定容器的首选尺寸
  • 根据布局规则对容器中的组件进行布局

FlowLayout 是一种奇怪的动物。它具有这两个功能。容器的首选大小假定所有组件都将布置在一行中。当遇到容器的最大宽度时,布局代码会将组件包装到下一行。然而,问题在于这些函数之间并不相互通信。当组件被包装到新行时,首选大小不会改变,因此您永远不会在额外的行上看到组件。

我们想要的是随着容器大小的变化动态计算首选大小。换句话说,随着容器宽度的变化,高度也需要重新计算。 WrapLayout 扩展了 FlowLayout 以实现此功能。这将导致容器的首选大小与容器的布局同步。

在下面的示例中,按钮面板被添加到 BorderLayout 的北部,蓝色面板被添加到中心。您可以像使用 FlowLayout 一样使用 WrapLayout:

 buttons.setLayout(new WrapLayout());

enter image description here
随着框架的尺寸调整得更小,按钮面板的高度将增加而蓝色面板将减小:

enter image description here

将面板添加到滚动 Pane 后,滚动 Pane 的大小不会改变,但会根据需要出现水平和垂直滚动条。

布局管理器的初始首选大小计算仍然假定所有组件都将显示在一行中。因此,如果您 p​​ack() 一个框架,则首选宽度可能会过大。您可以使用以下方法限制容器的宽度:

buttons.setSize(new Dimension(300, 1));

WrapLayout的全部代码:

import java.awt.*;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

/**
* FlowLayout subclass that fully supports wrapping of components.
*/
public class WrapLayout extends FlowLayout
{
private Dimension preferredLayoutSize;

/**
* Constructs a new <code>WrapLayout</code> with a left
* alignment and a default 5-unit horizontal and vertical gap.
*/
public WrapLayout()
{
super();
}

/**
* Constructs a new <code>FlowLayout</code> with the specified
* alignment and a default 5-unit horizontal and vertical gap.
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
* @param align the alignment value
*/
public WrapLayout(int align)
{
super(align);
}

/**
* Creates a new flow layout manager with the indicated alignment
* and the indicated horizontal and vertical gaps.
* <p>
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
* @param align the alignment value
* @param hgap the horizontal gap between components
* @param vgap the vertical gap between components
*/
public WrapLayout(int align, int hgap, int vgap)
{
super(align, hgap, vgap);
}

/**
* Returns the preferred dimensions for this layout given the
* <i>visible</i> components in the specified target container.
* @param target the component which needs to be laid out
* @return the preferred dimensions to lay out the
* subcomponents of the specified container
*/
@Override
public Dimension preferredLayoutSize(Container target)
{
return layoutSize(target, true);
}

/**
* Returns the minimum dimensions needed to layout the <i>visible</i>
* components contained in the specified target container.
* @param target the component which needs to be laid out
* @return the minimum dimensions to lay out the
* subcomponents of the specified container
*/
@Override
public Dimension minimumLayoutSize(Container target)
{
Dimension minimum = layoutSize(target, false);
minimum.width -= (getHgap() + 1);
return minimum;
}

/**
* Returns the minimum or preferred dimension needed to layout the target
* container.
*
* @param target target to get layout size for
* @param preferred should preferred size be calculated
* @return the dimension to layout the target container
*/
private Dimension layoutSize(Container target, boolean preferred)
{
synchronized (target.getTreeLock())
{
// Each row must fit with the width allocated to the containter.
// When the container width = 0, the preferred width of the container
// has not yet been calculated so lets ask for the maximum.

int targetWidth = target.getSize().width;

if (targetWidth == 0)
targetWidth = Integer.MAX_VALUE;

int hgap = getHgap();
int vgap = getVgap();
Insets insets = target.getInsets();
int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
int maxWidth = targetWidth - horizontalInsetsAndGap;

// Fit components into the allowed width

Dimension dim = new Dimension(0, 0);
int rowWidth = 0;
int rowHeight = 0;

int nmembers = target.getComponentCount();

for (int i = 0; i < nmembers; i++)
{
Component m = target.getComponent(i);

if (m.isVisible())
{
Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();

// Can't add the component to current row. Start a new row.

if (rowWidth + d.width > maxWidth)
{
addRow(dim, rowWidth, rowHeight);
rowWidth = 0;
rowHeight = 0;
}

// Add a horizontal gap for all components after the first

if (rowWidth != 0)
{
rowWidth += hgap;
}

rowWidth += d.width;
rowHeight = Math.max(rowHeight, d.height);
}
}

addRow(dim, rowWidth, rowHeight);

dim.width += horizontalInsetsAndGap;
dim.height += insets.top + insets.bottom + vgap * 2;

// When using a scroll pane or the DecoratedLookAndFeel we need to
// make sure the preferred size is less than the size of the
// target containter so shrinking the container size works
// correctly. Removing the horizontal gap is an easy way to do this.

Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);

if (scrollPane != null && target.isValid())
{
dim.width -= (hgap + 1);
}

return dim;
}
}

/*
* A new row has been completed. Use the dimensions of this row
* to update the preferred size for the container.
*
* @param dim update the width and height when appropriate
* @param rowWidth the width of the row to add
* @param rowHeight the height of the row to add
*/
private void addRow(Dimension dim, int rowWidth, int rowHeight)
{
dim.width = Math.max(dim.width, rowWidth);

if (dim.height > 0)
{
dim.height += getVgap();
}

dim.height += rowHeight;
}
}

引用:http://tips4java.wordpress.com/2008/11/06/wrap-layout/

关于java - swing flowlayout preferredSize 不会自动改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25337235/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com