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 <[email protected]> > 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 >> <[email protected]> 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 >>
