Monday March 23, 2009 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:
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:
scrollPane.setBorder(new EmptyBorder(new Insets(0,0,0,0)));
textPane.setFont(new java.awt.Font("American Typewriter", 0, 14));Here's what we get:
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:
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):