JavaFX: comparison of rich text components
Rich text component is a user interface component that displays text by styling various parts of it differently. Very often Rich Text components are used for editors. An example may be any code editor that supports highlighting. I needed such UI component for my latest application - The Console so now I’ll shortly discuss a comparison between few options:
- e(fx)clipse Runtime StyledTextArea
- RichTextFX
- JavaFX built-in TextFlow
- JavaFX built-in WebView
My requirements
- styling text and/or parts of it (as in HTML)
- changing styles at runtime
- modify previously added parts - it should be easy to track those parts
- events (e.g. clicking on URLs)
- select/mark any part of text with option to be copied
- efficient enough for big pile of text (rendering only visible parts)
- adding images would be a huge plus
Options I tried
After reading Experimenting with TextFlow, From StyledTextViewer to a StyledTextEditor and following posts on same blog I decided to not look at built-in JavaFX components. First I tried StyledTextArea, then RichTextFX and later the built-in options.
e(fx)clipse Runtime: StyledTextArea
What I really needed was **read-only **component to display colorful text with images. Setting editable property didn’t really work and I got problems when my other input component (a simple TextField) unfocused - I couldn’t focus it again.
It seems to be pretty efficient but I can’t display images between parts of text. I have read somewhere that it doesn’t support text wrap. I do can copy text and even paste it but there appeared focus issues again.
But the main issue here is a lack of easy way to track parts of text. Instead of saving some references to some elements like HTML DOM nodes I would have to save positions of text and update them if something else was edited.
Other than that this library is not documented, it’s really hard to find any examples and source code is placed on Eclipse git servers which I found about it because of link in blog post comment.
RichTextFX
This one worked well with focusing. It’s little easier to style parts of text (using StyleClassedTextArea class) for adding but - again, as with previous component, it’s hard to track parts of text for future edition by reference. Would need lots of manual work of saving line number/positions and updating them when something prior tracked element was modified.
I can wrap text here! But can’t inline images.
Couldn’t find documentation on this library but demos are on GH. Currently it needs a note there are some major differences between master branch and latest released version so if you’re looking at demos then make sure to compile library yourself or look at specific version git tag.
TextFlow
This one is pretty easy to use. TextFlow can contain Text nodes and ImageView nodes. Breaking lines is simply done by adding ‘\n’ inside of Text. Images can be inlined - e.g. images for emoticons.
Performance is rather questionable as shown in Experimenting with TextFlow but what hit me most is no possibility to mark/select text for copying. There’s a ticket around this feature but it seems to be abandoned: JDK-8092278.
WebView
WebView is just about HTML and it’s made on top of WebKit engine so it’s performance and rendering should be quite good and predictible. I was rather worried about memory usage and initialization time since it’s a native thing imported into VM world. Memory usage doesn’t extend in any noticable amount and initialization of engine is asynchronous - so it doesn’t kill my app for seconds at start. In the other hand the asynchronous loading makes me using BlockingQueue for a time when Document is not loaded.
Inside WebView JavaScript execution is possible. Text selection and copying works too. DOM nodes can be created using pure Java instead of JavaScript code injection. That’s important for me because I can save a reference to such nodes and later modify them the way I want.
My choice
My final choice is JavaFX built-in WebView. It provides me with all features I need and seems to be easier than I thought at first. Thanks to org.w3c.dom package I can save a reference to DOM element. DOM modification and styling is actually same as in web browsers so it’s pretty straightforward.
The only part I didn’t like about WebView was a need to deal with asynchronous. I add logs to my console at the start of the software while WebEngine is still loading. To deal with it I use BlockingQueue as you can see here.