getWidth()/getHeight() 和 getPreferredSize().width/height 有什么区别?

What is the difference between getWidth()/getHeight(), and getPreferredSize().width/height?

我正在尝试使用在调整 JFrame 大小时动态调整大小的键来绘制键盘。此外,键可以有不同的大小。

我有一个面板,其布局设置为 BorderLayout。在中心,我放置了一个面板,其布局设置为 GridLayout(5,1).

网格的每一行都是 JPanelFlowLayout。在每一行中,我计算每个按钮并通过调用 setPreferredSize 方法设置其首选大小。

当运行程序时,我只看到一些外观怪异的按钮。当我使用 getWidth()/getHeight()getPreferredSize().width/height 检查行面板时,我得到了不同的值:对于 getPrefereedSize().width ,我得到了我真正设置的宽度,但是对于 getWidth() 我的价值明显偏低。

getWidth()getPreferredSize().width 这两种方法有区别吗?

组件的 getWidth/getHeight return 当前尺寸。 getPreferredSize return 是组件想要获取的内容。例如,带有文本的按钮将 return 首选大小,因此文本将完全可见。

合理的布局管理器会向子组件询问它们的首选尺寸,并为它们提供这些尺寸。这将导致父组件的首选大小。如果父组件设置较小的尺寸,它就不能再强制子组件的首选尺寸,要么隐藏一些,要么使组件变小。

(这个问题有一个对应的问题:Java: Difference between the setPreferredSize() and setSize() methods in components。还有一些关于getSize()getPreferredSize()的问题,但我没有找到一个可以被认为是重复的。所以我们开始...)

Swing 中的组件通常有一个首选大小。这是调用 getPreferredSize 方法时 returned 的大小。这是组件 "like" 为了正确显示而应具有的大小。例如,具有特定文本和字体的 JLabel 将具有刚好足以显示整个文本的首选大小。

但是当一个组件显示在屏幕上时,可能无法以首选尺寸显示它(一些原因将在下面解释)。因此,当调用 getSize 时,该方法将 return 组件 当前 在屏幕上的 实际 大小。调整包含框架的大小时,组件也可能会调整大小,然后 return 又是一个不同的值。

(请注意,getSize() 基本上 return 是一个包含与 getWidth()getHeight() 编辑的 return 相同值的对象。


为什么不能始终确保实际尺寸与首选尺寸匹配:

Swing 中的布局通常由布局管理器处理。有关详细信息,请参阅有关 Laying Out Components Within a Container 的教程,但我将在此处尝试总结与此问题相关的部分。

此类布局管理器将尝试 以其首选大小布置组件。可以想象这是困难的,有时甚至是不可能的。想象一个带有 GridLayout(1,2) 的面板包含另外两个面板:

+---------------------+---------------------+
|                     |                     |
|  Preferred Size:    |   Preferred Size    |
|     400 x 300       |      100 x 200      |
|                     |                     |
+---------------------+---------------------+

GridLayout中,所有组件的大小必须相同。但他们的首选尺寸不同。所以布局管理器只是不能确保面板的实际尺寸与其首选相同] 尺寸。因此它以介于两者之间的折衷大小显示它们。 (它还可能考虑到最小和最大尺寸,使其更加困难......)。最后,例如,两个面板的大小可能是 (300,200) 像素,即使首选大小是 (400,300) 和 (100,200) 像素。


特别是关于您描述的布局:请注意 FlowLayout 在这里有点特殊。它将按照首选大小布置组件,如果 足够space。如果不够space,那么有些组件可能不可见。因此,您可以尝试将行中的 FlowLayout 更改为 GridLayout(1,n),其中 n 是该行中的键数。