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).
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?
