JavaFX Text Component


At the Roundup a few weeks ago we rewrote the old Swing JFlubber application to JavaFX. We had a brand new graphical design done in PhotoShop, and we hooked up the functionality with some swanky effects. I might get into that in another blog entry.



But one challenge we ran into was that of displaying text. In the Flubber application we need to have an editable text area where flub times are automatically inserted and the user can add additional comments. JavaFX makes it easy to throw some simple text in a design, but edit, scroll, and so on? Not yet.



Proper GUI components for JavaFX is coming. But in the mean time, there are some tricks you can use. Put simply, you can use a Swing text area, but without looking like Swing. Here's how. First, create a JavaFX scenegraph node for the Swing text component:


var textPane = new JTextPane();
var scrollPane = new JScrollPane(textPane);
var text: SwingComponent = SwingComponent.wrap(scrollPane);

Let's see how that looks:






Ugh!! Not what we want. Obviously, we don't want the text area to look like Swing... we have a nice background as part of the PhotoShop design that we want to use under below the text. But that's not hard to fix. Java colors have an alpha channel, for opacity. We can use a completely transparent background on the text area to make it just pass through its background (and we have to make the scroll pane nonopaque as well):


textPane.setBackground(new java.awt.Color(0,0,0,0)); // 0 opacity => 100% transparent!
textPane.setForeground(java.awt.Color.WHITE);
textPane.setCaretColor(java.awt.Color.WHITE);
scrollPane.setOpaque(false);

Let's try again:






Much better! But there is still a gray rectangle on top of the graphics, placed there by the border of the scrollpane. We can get rid of that too:


scrollPane.setBorder(new EmptyBorder(new Insets(0,0,0,0)));







Now we're talking! But the font is too small. Dick told me he wants to use a Courier font. So let's try this one:


textPane.setFont(new java.awt.Font("American Typewriter", 0, 14));

Here's what we get:






Ewwwwww! The font is not antialiased. I tried a bunch of things to fix this -- for example setting antialias rendering hints on the component itself, setting the aa system property, etc. It looks like there is a bug here in that the rendering hints aren't picked up properly for the wrapped Swing components. But I did find a workaround that works: We can set the antialiasing rendering hints directly on the graphics object ourselves. That means we need to get involved in the painting of the component itself, but luckily that's trivial. Instead of creating a new JTextPane, we'll create a simple subclass of it where we override the paint method to add the rendering hints:


import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JTextPane;

public class AntiAliasedTextArea extends JTextPane
{
@Override
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
super.paint(g);
}
}

Now we can just change


var textPane = new JTextPane();

to

var textPane = new AntiAliasedTextPane();

and we get this:






Ta-da!



But there is one more problem... What if we add a lot of text:






Scrollbars! We don't want those. This text pane won't be used for much text, so you can just move the caret around like in a text field to navigate the overflow content. So let's turn off the scrollbars:


scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

and with that, the text pane behaves exactly the way we want. Now you can manipulate text in the usual way: textPane.setText(string), textPane.getText(), etc.



While we're at it, let's fix the selection colors as well such that when you select text you don't get the telltale Swing light blue:


textPane.setSelectionColor(new Color(255, 255, 255, 50));
textPane.setSelectedTextColor(new Color(255, 255, 255, 255));

Note again how we can use transparency on this colors to give a nice glass effect on the selection (I also bumped up the font size):







Hopefully these tricks will help you with your text needs until we have real JavaFX components...


Comments:

i really dont like to see swing components in javafx, they just look ugly. we need skinnable ui controls as soon as possible

Posted by jorgemania on March 23, 2009 at 04:17 AM PDT #

Agreed - we need skinnable UI controls as soon as possible. But the point of this blog entry was that they don't -have- to look ugly! A proper FX text component would be better, but if you -need- text, the above tricks will hopefully be an okay temporary solution - if you look at the last screenshot it's not obvious that it's Swing!

Posted by Tor Norbye on March 23, 2009 at 04:32 AM PDT #

You did an excellent job of hiding the ugliness of Swing from the end user, but the hackery required at so many different levels of abstraction shows that the ugliness faced by the developer is as bad as it ever was. It will be interesting to see if JavaFX manages to get this right in the end.

Posted by Jim Elliott on March 23, 2009 at 06:01 AM PDT #

Hopefully the SwingComponent.wrap memory leak will be fixed by v1.1.1 :)

Posted by Jean Louis Bonneton on March 23, 2009 at 06:32 AM PDT #

real skinnable Swing components in JavaFX -

http://jfxstudio.wordpress.com/2009/02/18/something-usefull/

Posted by surikov on March 27, 2009 at 05:33 AM PDT #

About the font aa. I found on windows if i pass the jvm argument

-Dawt.useSystemAAFontSettings="gasp"

all fonts will have aa turned on. (that is all the fonts i've tested)

ant

Posted by Antoine Kurukchi on March 27, 2009 at 07:57 PM PDT #

Off topic..
I had a blog request and didn't know how to get it to ya.
Tor would you consider a 'how to optimize my netbeans usage' series of blog posts? I have heard many allusions over the years to your ability to use netbeans in a an optimal way. It would be really kewl if you could share a bunch of those.

Thanx,
LES

Posted by Les Stroud on March 28, 2009 at 02:30 AM PDT #

BTW, this link : http://net.tutsplus.com/videos/screencasts/how-i-can-code-twice-as-fast-as-you/ made me think of it. Obviously, we can be far more sophisticated in nb.

Posted by Les Stroud on March 28, 2009 at 02:32 AM PDT #

Hey m trying to develop a JavaFX application in which i need to import some documents that have text written on them (docs may be .txt or .jpg with text).If i import these documents as images text is not editable. Is there any way by which i can edit text on these documents in my application....help needed please respond :)

Posted by akanshaa on August 14, 2010 at 10:19 PM PDT #

Post a Comment:
Comments are closed for this entry.
About

Tor Norbye

Search

Archives
« July 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
       
Today