1

is there any way to determine the bounds (especially height and width) of a node which is already attached to a scene but set to invisible?

I want to show a label on screen only if its width exceeds 100px... but it is always 0:

@Override
public void start(Stage primaryStage) {
    Group root = new Group();
    Scene scene = new Scene(root, 500, 500, Color.BLACK);
    primaryStage.setScene(scene);
    primaryStage.show();

    Label n = new Label();
    n.setVisible(false);
    n.setStyle("-fx-background-color: red;");
    root.getChildren()
        .addAll(n);
    n.textProperty()
        .addListener((v, ov, nv) -> {
            System.out.println(n.getBoundsInParent());
            n.setVisible(n.getWidth() > 100);
        });
    n.setText("TEST11111111111111111111111");
}    

The result of the sysout: (also n.getWidth() is no better)

BoundingBox [minX:0.0, minY:0.0, minZ:0.0, width:0.0, height:0.0, depth:0.0, maxX:0.0, maxY:0.0, maxZ:0.0]

Is there any trick ?

Thanks all!

Defarine
  • 293
  • 5
  • 13
  • Use a `Text` node. When the `Text` node reaches the length you want, set the label with the `Text` node's text and show the label. https://stackoverflow.com/questions/19361211/measure-the-length-of-text-in-javafx – SedJ601 Nov 16 '17 at 19:51

1 Answers1

0

Your problem is that you are listening for changes to the text property and expecting the width of the node to be updated at that time - but it's not. The width of nodes are only calculated and set during a render pass which consists of an applyCSS and layout routine (see: Get the height of a node in JavaFX (generate a layout pass)). Your code incorrectly sets the node to invisible before the updated size of the node is calculated.

Instead of using a listener on the text property to determine visibility of the node, I suggest that you use a binding expression to create a direct binding on the visibility property to the desired width property. An example of this approach is provided below. You can see that the label only displays when the text to display is longer than the required width (in this case 100 pixels).

short text longer text

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class BoundSample extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        Pane root = new Pane();
        Scene scene = new Scene(root, 200, 100);
        primaryStage.setScene(scene);
        primaryStage.show();

        Label n = new Label();
        n.setVisible(false);
        n.visibleProperty().bind(n.widthProperty().greaterThan(100));

        TextField textField = new TextField("TEST11111111111111111111111");
        n.textProperty().bind(textField.textProperty());
        textField.relocate(0, 50);

        root.getChildren().addAll(n, textField);
    }
}
jewelsea
  • 150,031
  • 14
  • 366
  • 406