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

Eitanos30 :

I'm trying to paint a keyboard with keys that are dynamically resizing when the JFrame is resized. Also, the keys can be in different size.

I have a panel which has its layout set to BorderLayout. In the center I put a panel which has its layout set to GridLayout(5,1).

Each row of the grid is a JPanel with FlowLayout. In each of the rows I'm calculating each button and set its preferred size by calling the setPreferredSize method.

When running the program I see only some buttons in a weird appearance. When I'm checking the row panels with getWidth()/getHeight() and with getPreferredSize().width/height, I'm getting different values: For getPrefereedSize().width , I'm getting the width that I really set, but for getWidth() I'm getting a significantly lower value.

Is there a difference between both methods, getWidth() and getPreferredSize().width?

Marco13 :

(There is a counterpart of this question: Java: Difference between the setPreferredSize() and setSize() methods in components. And there are some other questions regarding getSize() and getPreferredSize(), but I didn't find one that could be considered as a duplicate. So here we go...)

A component in Swing usually has a preferred size. This is the size that is returned when calling the getPreferredSize method. It is the size that the component would "like" to have, in order to be displayed properly. For example, a JLabel with a certain text and font will have a preferred size that is just large enough to display the whole text.

But when a component is displayed on the screen, then it may not be possible to show it with its preferred size (some reasons will be explained below). So when calling getSize, the method will return the actual size that the component currently has on the screen. When the containing frame is resized, then the component may also be resized, and then return a different value again.

(Note that getSize() basically returns a single object that contains the same values as those returned by getWidth() and getHeight()).


Why it is not always possible make sure that the actual size matches the preferred size:

The layout in Swing is usually handled by layout managers. The details are explained in the tutorial about Laying Out Components Within a Container, but I'll try to summarize the part that is relevant for this question here.

Such layout manager will try to lay out components with their preferred size. One can imagine that this is difficult, and sometimes impossible. Imagine a panel with a GridLayout(1,2) that contains two other panels:

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

In the GridLayout, all components must have the same size. But their preferred sizes are different. So the layout manager simply cannot make sure that the actual sizes of the panels are the same as their preferred sizes. So it displays them with a size that is a compromise between the two. (It may also take into account the minimum and maximum size, making it even more difficult...). In the end, the size of both panels may, for example, be (300,200) pixels, even though the preferred sizes have been (400,300) and (100,200) pixels.


Specifically regarding the layout that you described: Note that FlowLayout is a bit special here. It will lay out the components with their preferred size, if there is enough space. If there is not enough space, then some components may not be visible. So you might try changing the FlowLayout in your rows to be a GridLayout(1,n), where n is the number of keys in this row.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=327837&siteId=1