0

I'm trying to pre-render some Text elements offscreen to retrieve their widths before rendering them later on-screen:

Group offScreenRoot = new Group();
Scene offScreen = new Scene(offScreenRoot, 1024, 768);
Set<Text> textSet = new HashSet<>();

Text textText = new Text(getText());
textSet.add(textText);

Text idText = new Text(getId());

textSet.add(idText);

for (String s : getStrings()) {
    textSet.add(new Text(s));
}
for (Text text : textSet) {
    text.setStyle("-fx-font-size: 48;"); // <- HERE!
    text.applyCss();
    offScreenRoot.getChildren().add(text);
}
for (Text text : textSet) {
    System.out.println(text.getLayoutBounds().getWidth());
}

I'm applying a large font size via CSS, but this doesn't get picked up. Instead, the Text is as wide as it would be, rendered in the default font size (I guess).

Is there a way to render a Text off-screen and get the actual width value as per CSS font size?

s.d
  • 4,017
  • 5
  • 35
  • 65

1 Answers1

0

I am not sure to understand the purpose of your code. It would have been easier with a MCVE, please keep it mind for the next time.

I think you made some simple mistakes. Looking at the applyCss definition You should apply the applyCss on the parent's node, not on the node.
Another thing important in the doc is :

Provided that the Node's Scene is not null

And unfortunately when you apply your CSS, the text's scene is null as it not yet added to his parent.

text.applyCss();
offScreenRoot.getChildren().add(text);

So there is two solutions, as described in the code below in comment (and especially in the for loop where you add Texts to the parent) :

public class MainOffscreen extends Application {

   private List<String> stringsList = new ArrayList<>();

   @Override
   public void start(Stage primaryStage) throws Exception {
      // Populates stringsList
      stringsList.add("String1");
      stringsList.add("String2");
      stringsList.add("String3");
      stringsList.add("String4");

      VBox offscreenRootVbox = new VBox(10.0);
      Scene offScreen = new Scene(offscreenRootVbox, 900, 700);

      // Replace the Hashset by list in order to keep order, more interesting for testing.
      List<Text> textSet = new ArrayList();

      // Text text.
      Text textText = new Text("Text");
      textSet.add(textText);

      // Text id.
      Text idText = new Text("Id");
      textSet.add(idText);

      // Populate String list.
      for(String s: stringsList) {
         textSet.add(new Text(s));
      }

      // Print the width of Texts before applying Css.
      for(Text text: textSet) {
         System.out.println("BEFORE Width of " + text.getText() + " : " + text.getLayoutBounds().getWidth());
      }
      System.out.println("\n----------\n");

      for(Text text: textSet) {
         text.setStyle("-fx-font-size: 48;"); // <- HERE!
         // First add it to the parent.
         offscreenRootVbox.getChildren().add(text);

         // Either apply the CSS on the each Text, or Apply it on the parent's Text, I choose the
         // second solution.
         // text.applyCss();
      }
      // Apply the css on the parent's node
      offscreenRootVbox.applyCss();

      for(Text text: textSet) {
         System.out.println("AFTER Width of " + text.getText() + " : " + text.getLayoutBounds().getWidth());
      }

      // primaryStage.setScene(offScreen);
      // primaryStage.show();
   }
}

And it gives this output :

BEFORE Width of Text : 22.13671875
BEFORE Width of Id : 10.259765625
BEFORE Width of String1 : 37.845703125
BEFORE Width of String2 : 37.845703125
BEFORE Width of String3 : 37.845703125
BEFORE Width of String4 : 37.845703125

----------

AFTER Width of Text : 88.546875
AFTER Width of Id : 41.0390625
AFTER Width of String1 : 151.3828125
AFTER Width of String2 : 151.3828125
AFTER Width of String3 : 151.3828125
AFTER Width of String4 : 151.3828125

Hope this helps you.

Pagbo
  • 691
  • 5
  • 13