TLDR: Skip to the Github link below.

So, I've run into an issue where a Label with wrap text set to true is only showing the first character of the text "as Kristoff (voice)" while all other kinds of texts show up correct (there's 100's of examples that all work, but only found one so far that doesn't work).  The label is placed in a VBox together with an Image and another wrap text Label.

Now, there is something really odd going on.  These VBox are placed in a 3x3 Grid, and basically all of the labels used are displayed correctly.  The Grid is fixed size, but the VBox content is rather flexible, and Labels that have a large amount of text should be wrapped and cause the Image in the VBox to become smaller to make space.

If I set the text of all these labels to a fixed value "as Kristoff (voice)" then ALL of them render incorrectly, only showing "a".  When I change the text to include a space behind the last character, then ALL of them render correctly.  In fact, any kind of change I do (like adding a "-" infront of this text) fixes the display problem.  So I suspect the issue has to do with the exact width of the text (126.0 in my case).

If I select the grid cell or move the cursor, the rendering immediately becomes correct for the cells involved, but all other cells keep showing just the "a".  If I hack LabeledSkinBase and remove the clip it generates if text doesn't fit, I can see that the ACTUAL content of the label is "a" and on the next line is "s Kristoff (voice)".  If I highlight the background of this label, I can see a box that would exactly fit the full text (and the box is only one line high), but it just isn't drawning it -- it only draws the "a" in the exact center of this box... It seems to know that the box should be that size to fit the label, but the text wasn't redrawn.

Now, because this layout is relatively complicated, with two reflowing labels and an Image that can "sacrifice" space if the labels demand more, I suspect JavaFX is doing multiple passes to get it correct -- debugging output does confirm that it does several attempts to get to the final size for this label (it starts with a width of 12.66 and a huge height wrapping on every character, then goes to 51x40 orso before settling on 126.0x18).

After a couple of hours debugging this and adding debug prints everywhere I started to suspect it was just not refreshing the Text or PrismTextLayout when it should; there is a LOT of caching and partial invalidation logic going on in these classes, most of which I just disabled during my search.

Finally I came to a piece of code in Text which is invalidating the text when `wrappingWidth` changes.  Changing only a single line there fixes my problem, but I'm unable to explain why.  I'm hoping someone can take a look at this code and say whether or not this change is indeed correct and the old code was incorrect...

A link to Github to the code involved: https://github.com/openjdk/jfx/blob/c6069d6845df4b90cca226e2b3dff49e3b48d8ac/modules/javafx.graphics/src/main/java/javafx/scene/text/Text.java#L669-L687

In this code there is a call to `needsTextLayout`.  Changing that to `needsFullTextLayout` fixes my issue.

The difference between `needsTextLayout` and `needsFullTextLayout` seems to be a call to TextLayout#setContent where the text and font is set.

If anyone knows this code that could help, or perhaps say if this change makes sense or not that would be helpful. I can be available for a call or whatever to give more details.

I would love to "fix" this in JavaFX via PR, but as I don't know how to test for this issue nor even how to describe it ("In super rare cases a wrappable label which in the end doesn't need wrapping only displays a single character"?) I'm unsure how I should file it to get a fix accepted :)

--John

Reply via email to