How to get the size of a label before it is laid o

2019-07-14 02:19发布

问题:

I read this old answer on how to accomplish this. But since it involves using impl_processCSS(boolean), a method that is now deprecated, I think we need to update the answer.

I've tried placing the label inside a HBox and then get the size of it, or getting the size of the HBox, without any luck. And I've also tried using .label.getBoundsInLocal().getWidth().

SSCCE: import javafx.scene.control.Label; import javafx.scene.layout.HBox; import javafx.application.Application; import javafx.scene.Scene;

public class SSCCE extends Application{

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        HBox root = new HBox();
        Label label = new Label("foo");
        System.out.println(label.getWidth());

        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

回答1:

Since JavaFX 8, the method you are looking for is applyCss().

As JavaDoc states:

apply styles to this Node and its children, if any. This method does not normally need to be invoked directly but may be used in conjunction with Parent.layout() to size a Node before the next pulse, or if the Scene is not in a Stage.

So you need to have the node in the container, and this one already on the scene, and also call layout().

@Override
public void start(Stage primaryStage) {
    Group root = new Group();
    Label label = new Label("foo bla bla");
    root.getChildren().add(label);
    Scene scene = new Scene(root);

    root.applyCss();
    root.layout();
    System.out.println(label.getWidth());

    primaryStage.setScene(scene);
    primaryStage.show();

}

Being the output: 17.818359375

Note I've changed HBox for Group, since:

a Group will "auto-size" its managed resizable children to their preferred sizes during the layout pass to ensure that Regions and Controls are sized properly as their state changes

If you use an HBox, you need to set also the dimensions of the scene:

@Override
public void start(Stage primaryStage) {
    HBox root = new HBox();
    Label label = new Label("foo");
    root.getChildren().add(label);
    Scene scene = new Scene(root,100,20);

    root.applyCss();
    root.layout();
    System.out.println(label.getWidth());

    primaryStage.setScene(scene);
    primaryStage.show();

}

Now the output is: 18.0