JavaFX: Difference in Label vs Text layouting

Viewed 373

I am encountering a strange issue when working with Label and Text in conjuction. Under simple scenario, if I provide a string to both Label and Text nodes with the same style, do they render differently? In my case it is happening. And I cant figure out why it is implemented in such way.

For example, for the given code:

Text text = new Text("Hello");
text.getStyleClass("myText");

Label label = new Label("Hello");
label.getStyleClass("myText");

and the css code:

.myText, .myText .text{
   -fx-font-family:"Verdana";
   -fx-font-size:18px;
}

If I render both label and text nodes in a layout (say HBox):

Case#1: (text first and then label)

hBox.getChildren().add(text,label);

The text bounds are smaller than the text node bounds of the label.

Case#2: (label first and then text)

hBox.getChildren().add(label,text);

The text bounds are same as the text node bounds of the label.

So in short, once the Label is rendered, the next rendering of all Text nodes (same string & style) will have the same size as Label.

Demo:

For a better understanding, if you check the below demo, the bounds of first Text node is different to the bounds of second Text node (because a Label is rendered prior to second Text node).

enter image description here

import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;


public class LabelVsText_Demo extends Application {

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

    Text labelTextNode;

    @Override
    public void start(Stage primaryStage) {
        GridPane root = new GridPane();
        root.setHgap(10);
        root.setVgap(10);
        root.setPadding(new Insets(10));

        Text txt1Text = new Text("Text 1:");
        Text labelText = new Text("Label:");
        Text txt2Text = new Text("Text 2:");

        Text text1 = new Text("AF421");
        text1.getStyleClass().add("myText");

        Label label = new Label("AF421");
        label.getStyleClass().add("myText");
        label.getChildrenUnmodifiable().addListener(
                (InvalidationListener) p -> label.getChildrenUnmodifiable().forEach(node -> labelTextNode = (Text) node));

        Text text2 = new Text("AF421");
        text2.getStyleClass().add("myText");

        Text b1 = new Text();
        Text b2 = new Text();
        Text b3 = new Text();

        Button button = new Button("Show Bounds");
        button.setOnAction(e -> {
            b1.setText(text1.getLayoutBounds().toString());
            b2.setText(labelTextNode.getLayoutBounds().toString());
            b3.setText(text2.getLayoutBounds().toString());
        });

        root.addRow(0, txt1Text, text1, b1);
        root.addRow(1, labelText, label, b2);
        root.addRow(2, txt2Text, text2, b3);
        root.add(button, 0, 3, 3, 1);

        Scene scene = new Scene(root, 1200, 400);
        scene.getStylesheets().add(LabelVsText_Demo.class.getResource("labeltext.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

And labeltext.css code is :

.myText, .myText .text{
   -fx-font-family:"Verdana";
    -fx-font-size:18px;
 }

Upon digging deep into the JavaFX code, it is noticed that the PrismTextLayout.java uses cache to get the bounds of already rendered Text (for same string and style). I believe which is good for performance boosting. But I am not expecting different results (in my case, different bounds for Text node)

Is this a bug in JavaFX or am I missing something?

0 Answers
Related