JavaFX - Inverting text color with a changing background.

Today, JavaFX 1.0 was announced (http://www.javafx.com), so I thought I would start chiming in again on some of the cool features of JavaFX.

I have been working with a customer to convert their Java Swing app over to JavaFX, and was intrigued with an indeterminate JProgressBar. An indeterminate JProgressBar has an internal rectangle, called a bouncing box, that continuously goes back and forth while running. What I noticed was that when the bouncing box moved over the progressString, it caused the text to change color. This was not a complete change, but only changed that part of the text that was covered by the bouncing box.

In the Swing source for JProgressBar (actually the Basic PLAF UI), this is done in the draw method, with the original text drawn once in the normal color (the selection background), followed by the alternate color, (the selection foreground), using a clip region. To duplicate this in JavaFX turns out to be similar.

I first created the bouncing box as a filled Rectangle and assigned it to an instance variable named "cursor". Then, I created a Text node with the background color, followed by a Text node with the foreground color. This second node is exactly the same as the first, except its stroke and fill colors are different. Furthermore, it takes a clip argument using the "cursor" rectangle. 


                cursor = Rectangle {
                    translateX: bind cursorX
                    translateY: bind borderWidth + 2
                    width: bind cursorWidth
                    height: bind height - borderWidth\*2 - 4
                    arcWidth: 5
                    arcHeight: bind height - borderWidth\*2 - 4
                    fill: bind background
                    cache: true
                },
                Text {
                    x: bind width/2 - geomText.boundsInLocal.width/2;
                    y: bind height/2 + geomText.boundsInLocal.height/2;
                    textOrigin: TextOrigin.BOTTOM
                    font: bind font
                    stroke: bind background
                    fill: bind background
                    content: bind text
                },
                Text {
                    x: bind width/2 - geomText.boundsInLocal.width/2;
                    y: bind height/2 + geomText.boundsInLocal.height/2;
                    textOrigin: TextOrigin.BOTTOM
                    font: bind font
                    stroke: bind foreground
                    fill: bind foreground
                    content: bind text

                    clip: bind cursor
                },


Now, the second Text does not display until the cursor Rectangle is over it, and only that part under the cursor is actually displayed.  Note that it is important that the clipped Text comes after the normal Text, because the last nodes are painted on top of previous nodes.

FX version of Indeterminate Progress Bar

The above screen snapshot shows the effect with the "ng..." of "Loading..." painted in white.

The complete code is available here!

Comments:

Neat! I had no idea you could clip on another defined shape. Thanks!

Posted by Eric Wendelin on December 15, 2008 at 04:10 PM EST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

jimclarke

Search

Categories
Archives
« April 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
   
       
Today