ComboBox item height bug
John Hendrikx
john.hendrikx at gmail.com
Mon Nov 10 01:10:37 UTC 2025
Hi Nir,
I got this mainly from non-public API Region#boundedSize
Node#minWidth and Node#maxWidth do document their respective behaviors,
but Node#prefWidth doesn't very explicitly state that it is clamped to
min/max.
--John
On 10/11/2025 00:34, Nir Lisker wrote:
>
> When it comes to size priorities (min, pref and max), minimum
> always wins, then comes maximum, then comes preferred.
>
> - min/pref/max height are 20/20/20
> - you set minimum to 6
> - end result: pref height wins with 20 as it is within the range
> [min, max]
> - you also set maximum to 1
> - end result: pref height is now outside the min/max range, so it
> is ignored; max is smaller than min, so it is ignored; min wins with 6
>
>
> Is this documented somewhere? I'd think it would answer a lot of
> confusing questions.
>
> On Sun, Nov 9, 2025 at 8:50 PM John Hendrikx <john.hendrikx at gmail.com>
> wrote:
>
> Hi,
>
> Normally a cell will have computed values for each of the
> min/pref/max. In your example, you were resetting the cells to
> USE_PREF_SIZE, but it makes little difference in the reasoning.
> All the size of a cell control (which is a label) will be the
> label's size to display its text. Its preferred height will be
> say 20. Its minimum will also be 20 to avoid cuts off. Its
> maximum will be 20 because there is no reason for it to take up
> more space. Those are the computes sizes. If you change all to
> USE_PREF_SIZE, nothing changes (since pref is 20, min and max will
> copy that). So:
>
> - min/pref/max height are 20/20/20
> - you set minimum to 6
> - end result: pref height wins with 20 as it is within the range
> [min, max]
> - you also set maximum to 1
> - end result: pref height is now outside the min/max range, so it
> is ignored; max is smaller than min, so it is ignored; min wins with 6
>
> If you however set minimum to USE_PREF_SIZE (as was done in your
> original code) or set it to 1, then you can use the pref size to
> change it. Either because 1 is smaller than the pref size, and so
> changing pref size to a smaller value won't make it go out of
> range; or in the USE_PREF_SIZE case, because min will simply track
> the pref size value and always change with it.
>
> --John
>
> On 09/11/2025 03:44, Cormac Redmond wrote:
>> Hi John,
>>
>> Thanks for the reply & details. One remaining question in my
>> previous mail however, was why a max *needs* to be set for min to
>> "win"...this still didn't make sense.
>>
>> Similarly, I had already tried prefHeight on its own, but it has
>> no effect (unless it's set to number higher than the computed
>> size of the cell, in which case it would increase the size).
>> Setting prefHeight and minHeight together though, can achieve
>> setting a "max height" though, just like setting a maxHeight and
>> minHeight as per my previous mail.
>>
>> But I've noticed that values prefHeight, minHeight, maxHeight are
>> all defaulted to USE_COMPUTED_SIZE (-1)..., *not
>> USE_PREF_SIZE* as you mentioned, and I assumed.
>>
>> So this explains the above behaviour and why several need to be
>> set: otherwise computed size wins one way or another.
>>
>> Although confusing initially, I assume there's no bug here and
>> that the developer needs to always check the underlying nature of
>> how pref/min/max default values are set for any node, in order to
>> know what and how to override their settings...?
>>
>>
>> If you want some validation, you can see these -1 defaults, via a
>> simpler example:
>>
>> public class ComboBoxHeightBug2 extends Application {
>> public static void main(String[] args) {
>> launch(args);
>> }
>>
>> public void start(Stage stage) {
>> ComboBox<Object> cb = new ComboBox<>();
>> cb.getItems().addAll("Apple", "Banana", "Carrot", "Lettuce");
>> cb.setCellFactory(_ -> new ListCell<>() {
>> protected void updateItem(Object item, boolean empty) {
>> super.updateItem(item, empty);
>> if (empty || item == null) {
>> setText(null);
>> setGraphic(null);
>> } else if (item instanceof Separator) {
>> setText(null);
>> setGraphic((Separator) item);
>> setDisable(true);
>> } else {
>> System.out.println("minHeight: " +
>> getMinHeight()); // -1
>> System.out.println("maxHeight: " +
>> getMaxHeight()); // -1
>> System.out.println("prefHeight: " +
>> getPrefHeight()); // -1
>> setText(item.toString());
>> setGraphic(null);
>> setStyle("");
>> }
>> }
>> });
>>
>> cb.getSelectionModel().selectFirst();
>> stage.setScene(new Scene(cb, 200, 100));
>> stage.show();
>> }
>> }
>>
>>
>>
>>
>> Kind Regards,
>> Cormac
>>
>>
>>
>> On Sun, 9 Nov 2025 at 00:06, John Hendrikx
>> <john.hendrikx at gmail.com> wrote:
>>
>> What you are likely seeing is that the minimum always wins
>> over the other values.
>>
>> The minimum height is set to the constant USE_PREF_SIZE,
>> which means that it will take the preferred size for the
>> minimum height.
>>
>> When it comes to size priorities (min, pref and max), minimum
>> always wins, then comes maximum, then comes preferred.
>>
>> So in this case, the preferred size is say 20. The minimum
>> follows the preferred, also 20. You set maximum to 1.
>> Minimum > Maximum, so Maximum is ignored.
>>
>> What you could try is set preferred size smaller instead;
>> there should be no need to change minimum or maximum then.
>>
>> --John
>>
>> On 08/11/2025 21:30, Cormac Redmond wrote:
>>> Hi,
>>>
>>> I have found a height bug when I am trying to reduce the
>>> height of one ComboBox item (a Separator) in a simple ComboBox.
>>>
>>> One would expect that to achieve this, you'd set the maximum
>>> height for that particular ListCell; but this has no effect.
>>>
>>> Instead what I need to do is set the /minimum/ height (but
>>> to the value I wish to be the maximum height), and I must
>>> *also *set the /maximum /height to any value (if I do not,
>>> my minimum height (i.e., my desired maximum) gets ignored)...
>>>
>>> For example, if I want the maximum height of this Separator
>>> to be 6, I must set the minimum height to 6 and I must set
>>> the maximum height to anything, even 1.
>>>
>>> Obviously this is counter-intuitive and doesn't
>>> make any logical sense.
>>>
>>> Example to reproduce (running from JFX master branch):
>>>
>>> public class ComboBoxHeightBug extends Application {
>>> public static void main(String[] args) {
>>> launch(args);
>>> }
>>>
>>> public void start(Stage stage) {
>>> ComboBox<Object> cb = new ComboBox<>();
>>> cb.getItems().addAll("Apple", "Banana", new
>>> Separator() , "Carrot", "Lettuce");
>>> cb.setCellFactory(_ -> new ListCell<>() {
>>> protected void updateItem(Object item, boolean
>>> empty) {
>>> super.updateItem(item, empty);
>>> if (empty || item == null) {
>>> setText(null);
>>> setGraphic(null);
>>> setStyle("");
>>> // Set back to default
>>> setMinHeight(USE_PREF_SIZE);
>>> setMaxHeight(Double.MAX_VALUE);
>>> } else if (item instanceof Separator) {
>>> setText(null);
>>> setGraphic((Separator) item);
>>> setDisable(true);
>>> setMinHeight(6); // This is required for
>>> any "max height" to apply, and appears to be the value that
>>> is used to determine height
>>> setMaxHeight(1); // Setting this (to 6)
>>> should work on its own, it doesn't, the value appears
>>> irrelevant -- but it MUST be set to get the separator height
>>> to be 6
>>> } else {
>>> setText(item.toString());
>>> setGraphic(null);
>>> setStyle("");
>>> // Set back to default
>>> setMinHeight(USE_PREF_SIZE);
>>> setMaxHeight(Double.MAX_VALUE);
>>> }
>>> }
>>> });
>>>
>>> cb.getSelectionModel().selectFirst();
>>> stage.setScene(new Scene(cb, 200, 100));
>>> stage.show();
>>> }
>>> }
>>>
>>> Note: I have noticed a few issues like this in general,
>>> whereby it requires trial and error to get /some/ desired
>>> height to apply; without any apparent logic as to how these
>>> values are being arrived at or how they're triggered to be
>>> used (I have logged bugs before on this)...
>>>
>>>
>>> Kind Regards,
>>> Cormac
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20251110/cb046cc3/attachment-0001.htm>
More information about the openjfx-dev
mailing list