获取多行流式布局的首选大小

7

我无法找到一种方法来调整swing GUI中的某些组件大小。一些自定义标签被添加到FlowLayout中,当重新调整对话框大小时它们的行为并不符合预期。 该面板是使用jgoodies forms框架构建的。

如果要使用此功能,请将FlowLayout添加到xy(3, y)中。

FormLayout layout = new FormLayout("r:d, 5px, f:d:g", // columns
            "p, p, 5px, p, 5px, p") // rows

当使用FlowLayout布局时,如果控件超出了容器的宽度,则会自动扩展并显示滚动条。

tags_scroll

如果使用:

FormLayout layout = new FormLayout("r:d, 5px, f:10:g", // columns
            "p, p, 5px, p, 5px, p") // rows

FlowLayout使用可用空间,第二行的项目会消失。
tags_vanish

我想将包含FlowLayout的每个行的高度扩展到组件的当前高度。不幸的是,首选大小总是对应于单行的高度。
另一种布局是否更合适?左侧加粗的文本应右对齐,然后是FlowLayout。

源码

[编辑]在尝试了数周后,实际问题可以归结为:
一组标签被添加到JPanel中。该JPanel应水平使用所有可用空间(对话框大小减去标记名称标签的宽度),并根据需要垂直扩展。如果JPanel的高度变大,则应出现垂直滚动条(水平滚动条从未显示)。 对话框可以显示多个JPanels,这些面板将一个接一个地显示(垂直方向)。

这里尝试使用GridBagLayout和WrapLayout

public class GridBagLayoutTagPanel extends JPanel {
private static final long serialVersionUID = -441746014057882848L;
private final int NB_TAGS = 5;

public GridBagLayoutTagPanel() {
    setLayout(new GridLayout());

    JPanel pTags = new JPanel(new GridBagLayout());
    pTags.setBackground(Color.ORANGE);
    GridBagConstraints c = new GridBagConstraints();
    c.ipadx = 5;
    c.ipady = 5;

    int rowIndex = 0;
    for (int i = 0; i < NB_TAGS; i++) {
        //add tag name
        JLabel lTagName = new JLabel(String.format("Tag %s:", i));
        lTagName.setFont(lTagName.getFont().deriveFont(Font.BOLD));
        c.fill = GridBagConstraints.NONE;
        c.gridx = 0;
        c.gridy = rowIndex++;
        pTags.add(lTagName, c);

        //add tag values
        JPanel pTag = new JPanel(new BorderLayout());
        pTag.add(new JLabel("+"), BorderLayout.LINE_START); //label used to add new tags
        pTag.add(getWrapPanel(), BorderLayout.CENTER); //the list of tag values
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 1;
        pTags.add(pTag, c);
    }

    //JScrollPane sp = new JScrollPane(pTags);
    //sp.setBorder(BorderFactory.createEmptyBorder());

    add(pTags);
    }

private static JPanel getWrapPanel() {
   JPanel p = new JPanel(new WrapLayout(FlowLayout.LEFT, 5, 0));

   for (int i = 0; i < 50; i++) {
           p.add(new JLabel("t" + i));
   }
   return p;
}

public static void main(String[] args) {
    JFrame f = new JFrame();
    f.getContentPane().add(new GridBagLayoutTagPanel());
    f.setSize(new Dimension(500, 300));
    f.setVisible(true);
}
}

你尝试过使用FormDebugUtils类和/或FormDebugPanel吗?这些调试工具帮助我几次看到了实际发生的情况。 - Robin
为什么你在代码中明显使用了 FormLayout,但还要声明 FlowLayoutFormLayoutFlowLayout 不相同。 - Andrew Thompson
@AndrewThompson FormLayout 不是问题所在。它会按照指示进行操作(例如第二个例子),使用可用的水平空间并根据添加到 FormLayout 的 FlowLayout 的首选高度来拉伸垂直空间。问题是首选高度从不改变。 - Philippe
3个回答

11
我希望能够将包含FlowLayout的每一行的高度扩展到组件的当前高度。不幸的是,首选大小始终对应于单行的高度。 Wrap Layout可以处理这个问题。

这似乎正是我正在寻找的。当我测试过后,我会将帖子标记为已回答。我很惊讶没有标准布局管理器像那样工作,因为它似乎是一个相当常见的用例。 - Philippe
我已经尝试了两个星期,但一直没有成功。每次使用不同的布局管理器都会出现问题。使用jgoodies FormLayout时,当需要计算高度和宽度时,组件的大小为0。使用GridBagLayout时,自动调整大小根本无法正常工作(如果有人想看示例,我可以提供)。使用SpringLayout时,使用Springutilities.makeGrid()时组件始终在垂直方向上扩展,并且使用Springutilities.makecompactGrid()时结果会显示在单行中。 - Philippe

3

在Rob的帮助下,使用他的WrapPanelScrollablePanel,现在它可以完美地工作了。

public class GridBagLayoutTagPanel extends JPanel {
  private final int NB_TAGS = 5;
  private final int NB_TAGVALUES = 50;

  public GridBagLayoutTagPanel() {
    setLayout(new GridLayout());

    ScrollablePanel pTags = new ScrollablePanel(new GridBagLayout());
    pTags.setScrollableWidth(ScrollablePanel.ScrollableSizeHint.FIT);
    pTags.setBackground(Color.ORANGE);
    GridBagConstraints c = new GridBagConstraints();
    c.ipadx = 5;
    c.ipady = 5;

    int rowIndex = 0;
    for (int i = 0; i < NB_TAGS; i++) {
      // add tag name
      JLabel lTagName = new JLabel(String.format("Tag %s:", i));
      lTagName.setFont(lTagName.getFont().deriveFont(Font.BOLD));
      c.fill = GridBagConstraints.NONE;
      c.gridx = 0;
      c.gridy = rowIndex++;
      c.weightx = 0; // keep minimum size of the cell containing the label when resizing
      c.weighty = 0;
      pTags.add(lTagName, c);

      // add tag values
      JPanel pTag = new JPanel(new BorderLayout());
      pTag.add(new JLabel("+"), BorderLayout.LINE_START); // label used to add new tags
      pTag.add(getWrapPanel(), BorderLayout.CENTER); // the list of tag values
      c.fill = GridBagConstraints.HORIZONTAL;
      c.gridx = 1;
      c.weightx = 1; // fill horizontally
      c.weighty = 1;
      pTags.add(pTag, c);
   }

   JScrollPane sp = new JScrollPane(pTags);
   sp.setBorder(BorderFactory.createEmptyBorder());

   add(sp);
  }

  private JPanel getWrapPanel() {
    JPanel p = new JPanel(new WrapLayout(FlowLayout.LEFT, 5, 0));

    for (int i = 0; i < NB_TAGVALUES; i++) {
      p.add(new JLabel("t" + i));
    }

    p.setSize(400, 1);
    return p;
  }

  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.getContentPane().add(new GridBagLayoutTagPanel());
    f.setSize(new Dimension(500, 300));
    f.setVisible(true);
  }
}

2

你尝试过MigLayout吗?它是我唯一使用的布局管理器,我从未遇到过无法实现的布局。


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