当JLabel的文本内容改变时,如何停止其改变大小?

6

我正在使用GridBag布局在代码中生成一些J组件并排列它们。我的布局由12行和3列组成,每一行都包含一个JSlider、一个JCheckBox和一个JLabel。以下是我用于生成UI的代码:

final int NUM_MOTORS = 12;

// This is the panel I'm adding the components to.
pnlMotorSliders.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();

for (int i = 0; i < NUM_MOTORS; ++i) {
    c.gridy = i;

    // Create the slider
    JSlider slider = new JSlider(SwingConstants.HORIZONTAL, 10, 4085, 10);
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 0;
    c.weightx = 0.9;
    pnlMotorSliders.add(slider, c);

    // Create the checkbox
    JCheckBox checkBox = new JCheckBox();
    checkBox.setOpaque(true);
    checkBox.setBackground(Color.blue);
    c.fill = GridBagConstraints.NONE;
    c.gridx = 1;
    c.weightx = 0.1;
    pnlMotorSliders.add(checkBox, c);

    // Create the current label
    JLabel label = new JLabel("0");
    label.setBorder(BorderFactory.createLineBorder(Color.red));
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 2;
    c.weightx = 0.2;
    pnlMotorSliders.add(label, c);
}

我遇到的问题是,当我设置任何一个JLabel中的文本时,它们会改变宽度并影响布局的其余部分,即使我设置的文本宽度明显小于JLabel的宽度。下面的两个屏幕截图演示了我的意思(红色和蓝色边框是为了调试而添加的):
更改JLabel文本之前的布局: ![](https://istack.dev59.com/Skl3U.webp)
更改底部JLabel文本后的布局。请注意,标签已变大。 ![](https://istack.dev59.com/tdLIg.webp)
我将底部JLabel上的文本设置为“-12”。即使JLabel的宽度似乎比文本宽得多,它仍然改变了大小,影响了布局的其余部分。
这是为什么?我该怎么做才能防止这种情况发生?

如果您防止标签根据需要扩展以容纳其文本,则可能会导致其变得无法读取;更多信息请参见此处 - trashgod
4个回答

6
您可以通过设置最小、首选和最大大小来调整标签的大小:
label.setMinimumSize(width, height);
label.setPreferedSize(width, height);
label.setMaximumSize(width, height);

同时,请确保将GridBagConstraints#fill设置为NONE,尽管我不确定是否仍然需要(我认为需要)。

编辑:顺便提一下,要想去除聚焦组件周围的那些难看的虚线,您可以将其设置为不可聚焦。

slider.setFocusable(false);

如果它不可聚焦,您如何通过键盘进行调整? - Catalina Island
@brimborium 嗯...还是不太明白。标签的首选宽度应该小于布局管理器为其分配的宽度(我的图像中的红色边框应该显示出来)。如果标签根据首选大小调整大小,则标签的大小应该比初始分配的空间更小,而不是更大。(续上) - Amr Bekhit
是的,Java布局并不是很好做。如果你正在寻找替代方案:MigLayout是一个非常好的Swing布局管理器。需要一些时间去掌握它,但我认为这是值得的。 - brimborium
3
不管问题是什么,调整组件的大小提示都不是一个解决方案...相反,使用一个合适的LayoutManager。 - kleopatra
1
@kleopatra 我告诉他使用MigLayout(就在你的评论之前)。但是问题要求使用GridBag LayoutManager的解决方案。不过还是谢谢你的评论,+1。 - brimborium
显示剩余5条评论

3

如果您的GridBagLayout中的组件不会水平填充其单元格,则“设置首选大小”解决方案才有效。

另一种解决方法是删除在该列中为组件分配的比重。然后可以手动控制列宽。设计时的一种简单方法是在具有所需特定宽度和零高度的列中放置JLabel。

为什么呢?需要深入了解GridBagLayout的工作原理:

GridBagLayout根据所需空间调整其列的大小,然后使用比重来分配“剩余”空间,以使得最终列宽加起来等于面板的总宽度。每列所需的空间是通过查找该列中组件的最宽部分来计算的。

每个组件所需的空间取决于它希望的宽度。在您的情况下,“0”高度的JLabel比“-12”高的JLabel小,因此列正在更改大小。

剩余空间根据分配给每列中组件的水平权重进行分配。权重被汇总,并基于该列对总数的百分比确定每个列的百分比。

列大小是基于所需空间加上剩余空间来确定的。因此,如果该列中的所有组件都没有比重,则您将不会获得任何剩余空间,因此不会出现动态更改。

第三种解决方案是不使用GridBagLayout。


0

这似乎不起作用。我在生成标签时添加了以下行:label.setSize(new Dimension(50, label.getPreferredSize().height));并将GridBag Fill设置为NONE。不幸的是,标签忽略了我的尺寸,使用它的默认大小,并在文本更改时改变其宽度。我尝试过在将标签添加到父容器之前和之后都设置标签大小。 - Amr Bekhit
我已经编辑了原始答案。进行了一些编码,似乎只需设置preferredSize就足够了(无论fill值是什么)。检查它是否适用于您,如果需要,我会发布一些代码。 - npe
不管遇到什么问题,调整组件大小提示都不是解决方案...相反,使用一个好的LayoutManager。 - kleopatra

0
label.setPreferredSize(new Dimension(width, height));

这是我能找到的唯一方法使其工作。对于我来说,设置最小值和/或最大值没有任何作用。此外,在Java 8上,我需要使用Dimension,否则以前不合适的尺寸不会改变。


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