为什么 BoxLayout 不允许我更改 JButton 的宽度,但允许我更改高度?

发布于 2024-09-18 13:16:07 字数 1184 浏览 7 评论 0 原文

我正在尝试让我的 JDialog 的布局适合我要移植到 Java 的程序的特定外观,我之前使用过几个 LayoutManager,并取得了巨大的成功出于某种原因,我似乎根本无法让这个工作。我的目标是让 JDialog 的右(东)侧按自上而下的顺序包含“查找下一个”和“取消”按钮,然后在下面添加任何额外的空间,以便这两个按钮始终位于 JDialog 的顶部,但由于某种原因 BoxLayout 不断忽略任何更改(这是我迷失的地方) 宽度的尝试JButton。代码如下。

JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
cancel.setPreferredSize(new Dimension((int)findNext.getPreferredSize().getWidth(),  
    (int)cancel.getPreferredSize().getHeight()));

JPanel example = new JPanel();  
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));  
example.add(findNext);
example.add(cancel);  
example.add(Box.createGlue());  

无论我尝试什么,cancel 始终保留其正常大小。我尝试使用与 setPreferredSize 相同的参数来使用 setMinimumSize()setMaximumSize() ,但没有成功。我什至尝试过 cancel.setPreferredSize(new Dimension(500, 500)); 并且按钮高度是唯一调整的,它仍然保留给定的默认宽度。

为了解决任何问题,这是它的样子(现在我已经完成了),您会看到“查找下一个”和“取消”按钮的大小不同。

示例图片

I'm trying to get the Layout of a JDialog of mine to fit a particular look that a program in which I'm porting to Java has, I've used several LayoutManagers before with great success yet for some reason I cannot seem to get this working at all. My goal is to have the Right (East) side of the JDialog contain a "Find Next" and "Cancel" button in a top-down order and then any extra space below so that the two buttons are always at the top of the JDialog, yet for some reason BoxLayout is continously ignoring any attempts at changing (this is where I'm lost) the width of a JButton. Code follows.

JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
cancel.setPreferredSize(new Dimension((int)findNext.getPreferredSize().getWidth(),  
    (int)cancel.getPreferredSize().getHeight()));

JPanel example = new JPanel();  
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));  
example.add(findNext);
example.add(cancel);  
example.add(Box.createGlue());  

No matter what I try, cancel always retains it's normal size. I've tried setMinimumSize() and setMaximumSize() with the same parameters as setPreferredSize with no luck. I've even tried cancel.setPreferredSize(new Dimension(500, 500)); and the buttons height was the only thing adjusted, it STILL retained the default width it was given.

To clear up any questions, here is what it looks like (now that I've finished it) and you'll see that the "Find Next" and "Cancel" buttons are not the same size.

example image

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

逆光飞翔i 2024-09-25 13:16:08

我知道这是一个老问题,但我真的没有看到一个好的解释。因此,为了偶然发现这一点的搜索者,我将添加我的两分钱。

在 Swing 中存在与调整组件大小相关的三种方法:setPreferredSize()、setMinimumSize() 和 setMaximumSize()。然而,重要的一点是,是否遵循这些方法取决于所使用的特定布局管理器。

对于 BoxLayout(原始海报使用的布局):

  • setMinimumSize() -- BoxLayout 采用此
  • setMaximumSize() -- BoxLayout 采用此
  • setPreferredSize() -- 如果 X_AXIS 为如果正在使用 Y_AXIS,则尊重正在使用的宽度,如果正在使用 Y_AXIS,则尊重高度。

OP 正在使用 Y_AXIS BoxLayout,这就是为什么只更改了他的高度。

更新:我为所有布局管理器整理了一个包含相同信息的页面。希望它可以帮助一些搜索者: http://thebadprogrammer.com/swing-layout-manager-尺寸/

I know this is an old question but I don't really see a good explanation. So for the sake of searchers that stumble upon this I will add my two cents.

There are three methods associated with sizing components in Swing: setPreferredSize(), setMinimumSize(), and setMaximumSize(). However, the important point is that it is up to the particular layout manager being used as to whether or not it honors any of these methods.

For BoxLayout (the layout the original poster is using):

  • setMinimumSize() -- BoxLayout honors this
  • setMaximumSize() -- BoxLayout honors this
  • setPreferredSize() -- if X_AXIS is being used width is honored, if Y_AXIS is being used height is honored

The OP is using a Y_AXIS BoxLayout which is why only his height was being changed.

Update: I put together a page with this same information for all of the layout managers. Hopefully it can help some searchers out: http://thebadprogrammer.com/swing-layout-manager-sizing/

微凉徒眸意 2024-09-25 13:16:08

您可能不需要 Box.createGlue(),它“Box .createVerticalStrut() 按钮之间,如下所示以及ControlPanel >模拟。

example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));
example.add(findNext);
Box.createVerticalStrut(10);
example.add(cancel);

附录:

添加setMaximumSize()使其工作。

这是垂直 BoxLayout 中具有相同最大宽度的组件的预期行为,如 框布局功能。容器的首选宽度成为(同样宽的)子容器的宽度,并且 X 对齐变得无关紧要。

example.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
Dimension d = findNext.getMaximumSize();
cancel.setMaximumSize(new Dimension(d));
example.add(findNext);
example.add(cancel);

You may not want Box.createGlue(), which "grows as necessary to absorb any extra space in its container." Instead, use Box.createVerticalStrut() between the buttons, as shown below and in the ControlPanel of this simulation.

example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));
example.add(findNext);
Box.createVerticalStrut(10);
example.add(cancel);

Addendum:

adding in setMaximumSize() made it work.

This is the expected behavior for components having identical maximum widths in a vertical BoxLayout, as described in Box Layout Features. The preferred width of the container becomes that of the (equally wide) children, and the X alignment becomes irrelevant.

example.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
Dimension d = findNext.getMaximumSize();
cancel.setMaximumSize(new Dimension(d));
example.add(findNext);
example.add(cancel);
琴流音 2024-09-25 13:16:08

正如该问题的评论中提到的,您可以通过切换到 setMaximumSize() 来修复它。但是,正如您所指出的,setPreferredSize() 不起作用。那么,这是怎么回事呢?

对于 Swing 的许多东西,使用 BoxLayout 时用于确定实际组件大小的属性有些随机(在我看来)。当确定如何呈现组件时,Swing 会调用布局管理器上的 layoutComponent(),该管理器会确定将所有内容放置在何处。

BoxLayoutlayoutComponent() 实现涉及对创建 SizeRequirements 对象,用于添加到 < 的每个组件的宽度和高度code>JPanel,基于其 getMinimum/Preferred/MaximumSize() 方法。

稍后,它调用 SizeRequirements.calculateAlignedPositions() 来确定每个组件的正确宽度值,因为您的方向是 BoxLayout.Y_AXIS (高度是使用不同的方法计算的) 。摘取源码,该方法的相关实现如下:

for (int i = 0; i < children.length; i++) {
    SizeRequirements req = children[i];
    //...
    int maxAscent = (int)(req.maximum * alignment);
    int maxDescent = req.maximum - maxAscent;
    //...
    int descent = Math.min(totalDescent, maxDescent);
    //...
    spans[i] = (int)Math.min((long) ascent + (long)descent, Integer.MAX_VALUE);
}

注意,totalDescent是可用宽度,因此descent始终设置为maxDescent,它基于 SizeRequirements.maximum,它取自 JButton.getMaximumSize()。随后在调用 JButton.setBounds() 时使用 spans[i] 的值作为宽度。正如您将注意到的,这里从未涉及 getPreferredSize(),这就是为什么设置它在这种情况下没有影响。

As mentioned in the comments on the question, you were able to fix it by switching to setMaximumSize(). However, as you noted, setPreferredSize() doesn't work. So, what's up with that?

With many things Swing, the properties used to determine the actual component size when using the BoxLayout are somewhat random (in my opinion). When determining how to render the components, Swing calls layoutComponent() on the layout manager, which is figures out where to position everything.

BoxLayout's implementation of layoutComponent() involves a call to a method that creates SizeRequirements objects for the width and height of each of the components you add to the JPanel, based on their getMinimum/Preferred/MaximumSize() methods.

Later, it calls SizeRequirements.calculateAlignedPositions() for determining the correct width values for each component, because your orientation is BoxLayout.Y_AXIS (The heights are calculated using a different method). Taking snippets from the source, the relevant implementation of this method is as follows:

for (int i = 0; i < children.length; i++) {
    SizeRequirements req = children[i];
    //...
    int maxAscent = (int)(req.maximum * alignment);
    int maxDescent = req.maximum - maxAscent;
    //...
    int descent = Math.min(totalDescent, maxDescent);
    //...
    spans[i] = (int)Math.min((long) ascent + (long)descent, Integer.MAX_VALUE);
}

Note that totalDescent is the available width, so descent is always set to maxDescent, which is based on SizeRequirements.maximum, which was taken from JButton.getMaximumSize(). The value of spans[i] is then used later in a call to JButton.setBounds() as the width. As you'll note, getPreferredSize() was never involved here, which is why setting it has no impact in this case.

栀梦 2024-09-25 13:16:08

通常,如果要确保 Swing 中组件的大小,您需要调用 setMinimumSize()setMaximumSize()SetPrefferedSize()相同的值。

Usually if want to ensure a size of the component in Swing you need to call setMinimumSize(), setMaximumSize(), and SetPrefferedSize() with the same value.

晨曦÷微暖 2024-09-25 13:16:08
button.setMaximumSize(getMaximumSize());
button.setMaximumSize(getMaximumSize());
霞映澄塘 2024-09-25 13:16:08

如果将按钮放在 GridLayout 面板中,它们将具有相同的宽度。

If you put your buttons in a GridLayout panel they will be the same width.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文