为什么BoxLayout不允许我改变JButton的宽度但让我改变高度?
我正在尝试获取我的JDialog
的布局以适应我移植到Java的程序的特定外观,我之前使用过几个LayoutManagers并取得了巨大成功但由于某些原因我似乎无法获得这工作完全没有。 我的目标是让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
始终保持正常的大小。 我尝试了setMinimumSize()
和setMaximumSize()
,其参数与setPreferredSize
相同,没有运气。 我甚至尝试过cancel.setPreferredSize(new Dimension(500, 500));
并且按钮高度是唯一调整的东西,它仍然保留了它给出的默认宽度。
要清除任何问题,这就是它的样子(现在我已经完成了),你会看到“查找下一个”和“取消”按钮的大小不同。
我知道这是一个老问题,但我没有看到一个很好的解释。 因此,为了找到偶然发现的搜索者,我将加上我的两分钱。
在Swing中调整组件大小有三种方法:setPreferredSize(),setMinimumSize()和setMaximumSize()。 但是,重要的一点是,它取决于特定的布局管理器是否遵循这些方法中的任何一种。
对于BoxLayout(原始海报使用的布局):
- setMinimumSize() –
BoxLayout
对此表示BoxLayout
- setMaximumSize() –
BoxLayout
尊重这一点 - setPreferredSize() – 如果正在使用X_AXIS,则使用宽度,如果正在使用Y_AXIS,则高度受到尊重
OP正在使用Y_AXIS BoxLayout,这就是为什么他的身高只会被改变。
更新:我为所有布局管理器整理了一个包含相同信息的页面。 希望它可以帮助一些搜索者: http : //thebadprogrammer.com/swing-layout-manager-sizing/
您可能不需要Box.createGlue()
,它“ 根据需要增长以吸收其容器中的任何额外空间”。 而是在按钮之间使用Box.createVerticalStrut()
,如下所示和此模拟的ControlPanel
中所示。
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS)); example.add(findNext); Box.createVerticalStrut(10); example.add(cancel);
附录:
添加
setMaximumSize()
使其工作。
这是垂直BoxLayout
具有相同最大宽度的组件的预期行为,如Box Layout Features中所述 。 容器的优选宽度变为(同等宽度)子容器的宽度,并且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);
正如对问题的评论中所提到的,您可以通过切换到setMaximumSize()
来修复它。 但是,正如您所指出的, setPreferredSize()
不起作用。 那么,那是什么呢?
有很多东西Swing,用于确定使用BoxLayout
时实际组件大小的属性有点随机(在我看来)。 在确定如何渲染组件时,Swing会在布局管理器上调用layoutComponent()
,这会找出放置所有内容的位置。
BoxLayout
的layoutComponent()
涉及对一个方法的调用,该方法根据getMinimum/Preferred/MaximumSize()
方法为添加到JPanel
的每个组件的宽度和高度创建SizeRequirements
对象。
稍后,它调用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()
从未涉及到此处,这就是为什么设置它在这种情况下没有影响。
通常,如果要确保Swing中组件的大小,则需要使用相同的值调用setMinimumSize()
, setMaximumSize()
和SetPrefferedSize()
。
如果将按钮放在GridLayout面板中,它们的宽度将相同。
button.setMaximumSize(getMaximumSize());