Why are some text bounds inconsistent in JavaFX and how can I avoid it?

Viewed 194

I'm using a Text node to compute the dimensions of a string, as described here, summarized as:

new Text("some text").getLayoutBounds();

The dimensions returned are not always the same at different execution points, for the same input string, and everything else being the same (font, etc.). It seems that the inconsistencies are somehow related to the interaction of the backspace with a TextArea, even if this TextArea is not related to the Text node.

It's an intermittent/non-deterministic problem, but others were able to reproduce it with the following code:

public class Test extends Application {
    private Text text = new Text();
    
    public static void main(String... args) {
        launch(args);
    }
    
    public void start(Stage stage) {
        TextArea textArea = new TextArea();
        textArea.textProperty().addListener((observable, oldValue, newValue) -> {
            text.setText(newValue);
            System.out.println(String.format("height=%.1f", text.getLayoutBounds().getHeight()));
        });

        stage.setScene(new Scene(new Group(textArea)));
        stage.show();
    }
}

Typing a few "X" characters, I get (on Windows): height=16.0. After typing backspace (but when there are still a few "X" characters in the string), I get height=17.0. If I type some more characters, the height stays 17.0, then arbitrarily shifts back to 16.0, then 17.0, etc. Other users report different kinds of erratic behavior.

  • If you replace the TextArea with TextField, the problem goes away (!)
  • It doesn't matter where the Text node is initialized.
  • While debugging, I see that that the valid flag is false in all cases in LazyBoundsProperty#get, so bounds seem to be recomputed for each new character.
  • I get the same behavior on JavaFX 11.0.2 as JavaFX 16.

What causes this inconsistency, and how can I avoid it?

0 Answers
Related