GridBagLayout:均匀分布的单元格
Posted
技术标签:
【中文标题】GridBagLayout:均匀分布的单元格【英文标题】:GridBagLayout: equally distributed cells 【发布时间】:2011-04-11 08:35:58 【问题描述】:是否可以使用 GridBagLayout 管理器完全模拟 GridLayout 的行为?
基本上,我有一个 8x8 网格,其中每个单元格应具有相同的宽度和高度。 GridLayout 自动执行此操作。但我想在网格中添加另一行和列,其大小与其他的 不同。该行/列应占用所有可能剩余的剩余空间(因为可用大小不能平均分配到 8 个单元格中)。这是否可能,或者我是否必须再次使用不同的布局管理器?
编辑
这是我想要实现的简单图形,简化为只有 4 个单元格:
彩色单元格是我添加到实际网格(灰色)中的单元格,该网格具有相同高度和宽度的单元格x
。所以网格的高度和宽度是4*x
。我现在希望其他单元格具有必要的宽度/高度(minimumSize)加上完整尺寸的其余可用宽度/高度。
如果整个面板的大小发生变化,灰色网格单元格应再次占用尽可能多的空间。
【问题讨论】:
【参考方案1】:在使用内置布局管理器尝试了许多不同的事情之后,我决定也为这个问题创建一个自定义布局管理器。我还没有这样做,因为我没有时间继续这个项目,但是当我完成后,我会确保在此处发布布局管理器代码,以便任何对类似解决方案感兴趣的人可以用。
编辑
didxga 在 cmets 中提醒我,我想发布我的解决方案。然而,在挖掘出当时的项目并查看它之后,我实际上无法发布我的解决方案,因为事实证明我从来没有创建它!
这是一个 uni 项目,于 2010 年 9 月中旬正式完成。我们实际上想在之后继续工作,这可能是我说我会发布它的原因(因为这是我想要改进的一件事),但我们从来没有真正做到这一点——可悲的是。相反,我只是省略了那些额外的列和行(顺便说一句,这意味着作为行/列的标签)。
所以,是的,我非常抱歉我无法发布符合我最初想要的布局...... :( 如果有足够多的请求这样的布局,我会创建它,但到目前为止,我不是真的很愿意再次深入研究 Java 布局;)
【讨论】:
你忘了贴吧? :) @didxga 好点,我完全忘记了这一点。我会尝试挖掘那个,并编辑我的答案:) +1 我 :-) 不明白 :-) 发生了什么,简单,GridBadLayout,SpringLayout 没有任何问题,或者例如,eeeght 特别活跃的线程太旧了(LayoutManagers API 中的一些变化) ) @mKorbel 制作自己的 LayoutManager 几乎总是一个坏主意。它往往会起作用,除非它不起作用,例如当您更改周围的布局约束时,或者当新版本的 Swing 假定 LayoutManager 所做的更多事情时,自制的 LayoutManager 不会观察到 - 除了在新解释实际上很重要的极端情况下,您不会注意到。这是让你的代码变得脆弱的好方法,除非你投入到让 LayoutManager 随时了解有关 Swing 的所有新闻。【参考方案2】:您没有在 JTable 中这样做是有原因的吗?似乎就是它的用途。使用适当的单元格渲染器,您可以在单元格中放置您想要的任何内容。
http://www.java2s.com/Code/Java/Swing-Components/TableRowHeaderExample.htm
【讨论】:
【参考方案3】:如果您不必绑定到 GridBagLayout,您应该查看 MigLayout 库。您可以按照以下方式进行操作:
MigLayout layout = new MigLayout(
"", // Layout Constraints
"[10][10][10][10]", // Column constraints
"[10][10][10][10]"); // Row constraints
【讨论】:
在阅读了这个布局管理器的快速入门指南之后,我认为这基本上是 GridBagLayout 所希望的。它的工作方式与 GridBagLayout 类似,但看起来更简单且定义明确。【参考方案4】:将固定单元的GridBagConstraints
的weightx
和weighty
设置为0
,将fill
设置为NONE
。对于浮动单元格设置fill
至BOTH
,对于应该只水平扩展的浮动单元格设置weightx
至1
,对于垂直扩展单元格设置weighty
至1
。
单元格只有在它们有任何内容时才会展开,所以你需要用一些东西填充它。我选择了JLabel
s 并为固定单元格中的标签设置了固定尺寸。在调整大小时,您需要重新计算尺寸并调用invalidate()
重新计算布局。
这是w
x h
网格的示例:
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GridBag
public static void main(String[] args)
final JFrame f = new JFrame("Gridbag Test");
final Container c = f.getContentPane();
c.setLayout(new GridBagLayout());
final Dimension dim = new Dimension(70, 70);
final int w = 4;
final int h = 4;
final JLabel[] yfloating = new JLabel[w];
final JLabel[] xfloating = new JLabel[h];
final JLabel[][] fixed = new JLabel[w][h];
// adding the vertically floating cells
final GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.BOTH;
gc.weightx = 0.0;
gc.weighty = 1.0;
for(int i = 0; i < w; ++i)
yfloating[i] = new JLabel("floating " + i);
yfloating[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
yfloating[i].setHorizontalTextPosition(JLabel.CENTER);
yfloating[i].setVerticalTextPosition(JLabel.CENTER);
gc.gridy = 0;
gc.gridx = i+1;
c.add(yfloating[i], gc);
// adding the horizontally floating cells
gc.fill = GridBagConstraints.BOTH;
gc.weightx = 1.0;
gc.weighty = 0.0;
for(int i = 0; i < w; ++i)
xfloating[i] = new JLabel("floating " + i);
xfloating[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
xfloating[i].setHorizontalTextPosition(JLabel.CENTER);
xfloating[i].setVerticalTextPosition(JLabel.CENTER);
gc.gridy = i+1;
gc.gridx = 0;
c.add(xfloating[i], gc);
// adding the fixed cells
gc.fill = GridBagConstraints.NONE;
gc.weightx = 0.0;
gc.weighty = 0.0;
for(int i = 0; i < w; ++i)
for(int j = 0; j < h; ++j)
fixed[i][j] = new JLabel("fixed " + i);
fixed[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
fixed[i][j].setMaximumSize(dim);
fixed[i][j].setMinimumSize(dim);
fixed[i][j].setPreferredSize(dim);
gc.gridx = i+1;
gc.gridy = j+1;
c.add(fixed[i][j], gc);
c.addComponentListener(new ComponentAdapter()
@Override
public void componentResized(ComponentEvent e)
final Component comp = e.getComponent();
final int newSize = Math.min(comp.getHeight() / h, comp.getWidth() / w);
final Dimension newDim = new Dimension(newSize, newSize);
for(int i = 0; i < w; ++i)
for(int j = 0; j < h; ++j)
fixed[i][j].setMaximumSize(newDim);
fixed[i][j].setMinimumSize(newDim);
fixed[i][j].setPreferredSize(newDim);
comp.invalidate();
);
f.pack();
f.setVisible(true);
【讨论】:
【参考方案5】:所有值都在GridBagConstraints
中设置。
如果您想固定 8x8 网格,可以设置 ipadx
和 ipady
值。
然后将新行/列的weightx
和weighty
值设置为1.0
,并将fill
设置为FULL
。
您的额外行/列将随着剩余的空间展开。
如果您还想扩展 8x8 网格,那就更复杂了。除了 weightx
和 weighty
值之外,您还可以调整 ipadx
和 ipady
值。或者为 8x8 网格制作一个面板,并在其中使用 GridLayout
。在面板和附加的行/列上使用您的GridBagLayout
。
【讨论】:
是的,我希望实际网格根据需要扩展,每行/列 8 个单元格大小相等,第 9 个单元格具有最小宽度/高度 + 其余可用宽度/高度。我不确定额外的面板是否可以工作,因为额外的行应该有 9 个单元格,其宽度与网格的其余部分相同,而额外的 9 列单元格的高度相同。基本上,额外的行/列应该包含单元格的标签。 将fill
设置为FULL
? GridBagConstraints
中没有 FULL
常量(也没有 FILL
)。以上是关于GridBagLayout:均匀分布的单元格的主要内容,如果未能解决你的问题,请参考以下文章