A reoccuring question in stackoverflow is how to present:
- Large amounts of editable text
- Display text paragraphs with words in different colors, sizes, … and optionally make them editable
In the following post I’d like to shade some light into this area of JavaFX and propose solutions allowing you to deal with them efficiently using runtime components developed as part of e(fx)clipse.
Displaying text
First of all to represent text the basic JavaFX classes you need to be aware of are:
javafx.scene.text.Text
: Allows you to render a text chunk with a given color, font-size, font-family, …javafx.scene.text.TextFlow
: Allows you to layout text nodes mixed with other content like images, shapes, …
So the first conclusion we could draw from this information is that to display styled text we create a TextFlow
, put Text
elements with different color & font settings into it, embed the TextFlow
into a ScrollPane
and are done.
If you implement this you get something like this:
I’ve written more on this at https://tomsondev.bestsolution.at/2013/02/14/experimenting-with-textflow-from-javafx8/
Mission accomplished? Almost until you notice that performance for big amounts of styled text are horrendous because the complete text has to be renderer although you only see 60 lines! Other problems: E.g. you don’t have a cursor so selecting and copying lines from the text are not possible. Bottom line: We need to get smarter but before we do so we look into editing of text.
Editing text
There are 3 main built-in controls to edit text:
javafx.scene.control.TextField
: Edit a single line of textjavafx.scene.control.TextArea
: Edit multi line textjavafx.scene.web.HTMLEditor
: Edit styled text with the help of WebView
HTMLEditor
solves a very special usecase so I’m not looking into it in this post. TextField
is only for one line so there’s only TextArea
left for larger chunks of text but TextArea
has multiple draw backs:
- You can not have different styled areas the complete text has to have one font, color, …
- It is totally inefficient because for rendering it uses 1 big
Text
-Object, for a few lines this is ok but if you have text with more than thousand lines you’ll run into troubles
To sum up: JavaFX comes by default with NO control that allows you edit & display large text.
Text editing extensions coming with e(fx)clipse
Displaying small amount of styled text
In the upcoming 1.2.0 release we’ll provide you org.eclipse.fx.ui.controls.styledtext.StyledString
which implements the CharSequence
interface and a static helper which allows to generate a scenegraph node from it.
Useage looks like this:
StyledString s = new StyledString(); s.appendSegment("This","default-text"); s.appendSegment("is bold","bold-text"); s.appendSegment("and red","red-text"); s.appendSegment("and bold & red","bold-text","red-text"); Node n = Util.toNode(s); // ...
The 2nd, 3rd, … argument are CSS-Styleclasses!
Displaying and editing large amounts of text
While the above method is easy to use it is not solving the problem for large texts (styled or not) nor does it help you with editing, … in fact it simply uses the TextFlow
approach hiding the details from you.
To solve the problem of editing and displaying large text we need a control who virtualizes the Text-Elements to display and only the lines visible in the UI are part of the Scenegraph. Implementing something like this is not hard but it also is not needed because JavaFX comes with controls who work like this: All *View
controls like TableView
, ListView
and TreeView
are virtual in the sense that they only create as many ListCell
, TreeCell
, … as you see on screen.
Based upon this knowledge we implemented a StyledTextArea
which has a similar API than SWT-StyledText
to display and edit large styled texts, rendering 100,000 lines of code works in no time!
Useage is as simple as:
StyledTextArea t = new StyledTextArea(); t.getStylesheets().add(getClass().getResource("test.css").toExternalForm()); t.getContent().setText("This is a styled text!\nThis is the 2nd line with data\nBlaBla"); t.setStyleRanges( new StyleRange("text-highlight",0,30,null,null) , new StyleRange("text-highlight",34,5,null,null) );
Pingback: JavaFX links of the week, January 12 // JavaFX News, Demos and Insight // FX Experience
Hi Tom,
Is your StyledTextArea still based on TextFlow? Do you have the code posted somewhere?
Thanks,
Jim
http://git.eclipse.org/c/efxclipse/org.eclipse.efxclipse.git/tree/bundles/runtime/org.eclipse.fx.ui.controls
I’m pretty interested in this solution for a large editable text area with ability to add images. It would be a really nice solution, but the link above is pretty unclear and the explanation above kind of leaves off suddenly without really clearly outlineing the final code.
look at the latest post on this blog to get more information about our control – still I guess it is not suitable for your needs as we are NOT providing support to add images, … . we are currently concentrating our efforts on a widget to develop code-editors
Your example shows a StyledTextArea consisting of two (short) lines of text, The topic of this blog is supposed to address displaying large amounts of styled text. Please show an example of how you support over 100,000 lines of text. I tried to use your StyledTextArea with a 16Mb file and it basically behaves the same way that the basic JavaFx TextArea does — namely it locks up the application because it can’t handle and can’t “virtualize” the content of the file that isn’t displayed.
I used StyledText to show colored java files more than 100k lines – in https://m.youtube.com/watch?list=PLPIzp-E1msrZz6RNdbDiK0nKuxAUZPs77&v=r7AMOmjQDlw i measured the performance – so please file a ticket at https://github.com/eclipse/efxclipse-rt with a test case to reproduce
Tom,
My apologies. After reviewing your presentation and looking through other sample/demo code I discovered that I was using the StyledTextArea content() incorrectly. The delay in loading was due to errors in my own code.
Thanks for the quick response and the pointer to your presentation — it was very helpful.
Cheers!
No worries we are working on a complete rewrite of StyledText fixing problems we have today like no vertical virtualization, too many scenegraph nodes, invalid vertical scroll, …
Does Java FX 12 come with a built-in solution to this issue?
no
Hi, is it possible to add click listener for StyleRange ?
not there but there’s API to add clickable areas, … . Please ask at the forum https://www.eclipse.org/forums/index.php/f/259/