import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Control; import javafx.scene.control.Label; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; public class MultilineLabelInHboxTest extends Application { public static final int CIRCLE_RADIUS = 20; public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Multi-line Label in HBox Test"); System.out.println("HBox 1 containing Label 1 is the broken one"); // create some sample text to display final String seed = "Every good boy deserves fruit;"; final StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10; i++) sb.append(seed); final String testString = sb.toString(); // create a HBox with a circle and a label inside (will not be sized as expected, label will be sized to the circles height). Label brokenLabel = new HeightReportingLabel(testString); brokenLabel.setWrapText(true); HBox brokenBox = makeBox(brokenLabel, Color.RED); brokenBox.setStyle("-fx-background-color: wheat"); // create a HBox with a circle and a label inside (will be sized as expected, label will be sized to all of it's text is displayed). Label okLabel = new HeightReportingLabel(testString); okLabel.setWrapText(true); HBox okBox = makeBox(okLabel, Color.GREEN); okBox.setStyle("-fx-background-color: lightgray"); // place HBoxes in a VBox so that they get re-sized. final VBox vbox = new VBox(); vbox.getChildren().addAll(brokenBox, okBox); Scene scene = new Scene(vbox, 400, 400); // manually overriding the label's computed width somewhat strangely allows the layout manager to correctly calculate the label's preferred height. okLabel.prefWidthProperty().bind(scene.widthProperty().subtract(CIRCLE_RADIUS * 2).subtract(5)); // subtract the width of the circle and hbox spacing. // display the scene. primaryStage.setScene(scene); primaryStage.show(); } private HBox makeBox(Label label, Color circleColor) { final HBox hbox = new HeightReportingHBox(); hbox.setSpacing(5); hbox.setFillHeight(false); // keep children at their preferred size, don't try to resize them to fill the hbox. hbox.getChildren().addAll( new Circle(CIRCLE_RADIUS, CIRCLE_RADIUS, CIRCLE_RADIUS, circleColor), label ); return hbox; } } class HeightReportingHBox extends HBox { static int nBoxes = 1; final int boxNum = nBoxes++; double priorPrefHeight = Control.USE_COMPUTED_SIZE; @Override protected double computePrefHeight(double v) { double h = super.computePrefHeight(v); if (h != priorPrefHeight) { priorPrefHeight = h; System.out.println("HBox " + boxNum + " Computed Pref Height: " + h + " for width " + v); } return h; } } class HeightReportingLabel extends Label { static int nLabels = 1; final int labelNum = nLabels++; double priorPrefHeight = Control.USE_COMPUTED_SIZE; HeightReportingLabel(String s) { super(s); } @Override protected double computePrefHeight(double v) { double h = super.computePrefHeight(v); if (h != priorPrefHeight) { priorPrefHeight = h; System.out.println("Label " + labelNum + " Computed Pref Height: " + h + " for width " + v); } return h; } }