ComboBox item height bug
Nir Lisker
nlisker at gmail.com
Sun Nov 9 23:34:15 UTC 2025
>
> 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/d88172d0/attachment-0001.htm>
More information about the openjfx-dev
mailing list