Here's a solution where you can also set a min and max width based on the size of the unclipped content.
For example, if you want to limit how much the label can get clipped and how long the label can be, but otherwise have the label width be the exact length necessary to show the full content. Here I show at least half of the unclipped width and at least 50px, but max 200px:
label.minWidthProperty().bind(Bindings.createDoubleBinding(
() -> Math.max(label.prefWidth(-1) / 2, 50), // Show at least half of content and at least 50px
label.textProperty(), label.graphicProperty(), label.prefWidthProperty(), label.layoutBoundsProperty()));
label.maxWidthProperty().bind(Bindings.createDoubleBinding(
() -> Math.min(label.prefWidth(-1), 200), // Show content up to 200px
label.textProperty(), label.graphicProperty(), label.prefWidthProperty(), label.layoutBoundsProperty()));
This is robust to changes in the label text or graphic. If you're going to change other things affecting the content size after the label is rendered then you may need to add some other observables to the list of dependencies, e.g. label.graphicTextGapProperty()
.