I recently attended
theJavaOne2012 conference
hosted byOraclethis
past October. My main goal was to focus on all things relating to
client-side Java, even if the sessions didn’t contain “JavaFX” in
the title. To my surprise, I received much more than I bargained
for. I attended sessions involving technologies such as
Dolphin,Griffon,Java
Embedded, JavaFX 8,
etc.

Figure 1: Tron Legacy style clocks with
JavaFX

I couldn’t help but drool
over the newJavaFX 8‘s 3D
APIs. However, another
one of my intentions was to look at the
many new features that were added to the currentrelease of
JavaFX 2.2.In particular, one feature that comes to mind is the highly
anticipated Canvas API. In this article, you will learn about some
of the performance characteristics when using
JavaFX’s
Canvas API and later, I will
share some code and teach you how to build an animated clock using
only the Canvas API on JavaFX’s scene graph as opposed to the
vector based counterparts (JavaFX 2.1 and earlier).

Of the many JavaFX sessions
at the JavaOne 2012 conference, one session, in particular, which
stood out was (CON6784
–
JavaFX Graphics Tips and Tricks) with Richard Bair. Mr. Bair, a
JavaFX Architect, discussed JavaFX 2 and JavaFX 8’s graphic
rendering performance in comparison with all of the major browsers
on popular desktop operating systems (Windows, Linux/Ubuntu, and
Mac OS X). The benchmark (following theGUIMark
2) results were categorized by
‘Vector’ and ‘Bitmap’ graphics rendering strategies. Familiar to
most HTML5 Web developers, using the ‘Vector’ rendering strategy is
simply synonymous to theSVG(XML representation of scalable vector graphics). In
addition to this, the ‘Bitmap’ rendering strategy is equivalent to
the use of the popular HTML5 Canvas
APIusing the JavaScript
language.

When involving the vector
rendering strategy, the performance numbers showed that JavaFX had
outperformed all of its competitors with the exception of the
Safari browser on Mac OS X. Similarly, when involving the bitmap
rendering strategy, the performance metrics indicate that the
JavaFX Canvas API outperformed all the browsers by a significant
amount. Mr. Bair did a great job in explaining when, why, and how
to choose between the two rendering strategies. Mr. Bair also
points out that, in some scenarios, JavaFX vector graphics can even
outperform JavaFX canvas. He also suggested that, when using one
technique over the other, the only way to really get a more
accurate picture is to profile the application. Of course, much
more was discussed in his talk. However, in this article I merely
wish to point out the relevant bits of information relating to the
Canvas API.

In the world of JavaFX, a
scene graph is mainly based on the ‘Vector’ rendering strategy
which calculates shapes and paths as scene graph nodes which are
easily scaled. For those developers who recall prior to JavaFX 2.2,
you will remember when there was not an ability to handle bitmap
graphics (pixel pushing). You are probably wondering, “How do you
render using the ‘Bitmap’ strategy onto the JavaFX vector based
scene graph?” Since the release of JavaFX 2.2, the JavaFX team
created the Canvas API. The Canvas API is actually a JavaFX node
called theCanvasclass. Since
theCanvasclass
extends fromjavafx.scene.Nodeclass, it is basically a scene graph node like
any other JavaFX node, except you have the ability to draw directly
and manipulate pixel data using graphics primitives (Canvas API)
onto the surface (GraphicsContext).

How do you draw on the
Canvas node?

To draw on a Canvas, you must first instantiate
aCanvasnode with a width and
height. After instantiating aCanvasclass, you will need to
obtain its
GraphicsContextobject. To obtain
theGraphicsContext,you simply invoke
itsgetGraphicsContext2D()method. TheGraphicsContextclass has methods enable
the developer to access many of the graphics drawing primitives.
These drawing primitives provide ways to draw shapes, fill colors,
set strokes, apply images, draw text, and much more. Please refer
to the JavaDoc for details relating to theGraphicsContextclass.Listing 1demonstrates the basics
of drawing onto theGraphicsContext.

Figure 2: The
basics

When creating an instance of aCanvasclass, you will have an
opportunity to place it into the scene graph like any other JavaFX
node. SinceCanvasis a JavaFXNodeclass, the
developer (user of the API) is free to treat it like any other node
in the scene graph. This means that you have the ability to apply
effects, transforms, and animations. One of the main advantages of
the Canvas API is that you can draw as many things on the graphic
context (bitmap surface) which is similar to the vector rendering
strategy.

However, instead of many nodes on the scene graph, all of
the drawings on the canvas are encapsulated in one node, thus
increasing performance. Remember, cutting down on the number of
node objects on the scene graph helps to achieve better
efficiencies such as graph walking.

A downside to using the Canvas API is that the developer
must draw things from scratch and handle efficiencies on their own
(such as calculating dirty regions for optimization). This is
why,in some cases, JavaFX’s
vector based strategy is able to excel in performance. These
advancements in performance are due to its ability to detect dirty
regions, offer caching hints and perform other tricks under the
covers. Everything boils down to what you are really trying to
achieve and the desired effect.

If you’ve dabbled with HTML5
development, you’ll notice JavaFX’s Canvas API was designed to look
similar to HTML5’s Canvas API (no coincidence). I was a bit
surprised that the programming interfaces didn’t follow the Java 2D
API (of which I’m a big fan). However, I quickly got over it. Many
of the popular HTML5/JavaScript examples on the net can be easily
ported to the JavaFX Canvas API because of their similar naming
conventions. (Note:In order
to use the Canvas API, you must install JavaFX 2.2 or a later
version.)

With all the excitement
surrounding JavaFX’s Canvas API, I decided to take it out for a
spin. Since JavaFX’s Canvas API has so many features, I will only
give you a quick glimpse by presenting a futuristic stylized clock
reminiscing of aspects of the movieTron
Legacy.The clock was inspired by a user namedBurnwell88at
DeviantArt. The clock was developed using theRainMeterdesktop theme maker. In
my concluding statements, I will list some of the many features
related to the Canvas API that won’t be discussed in this
article.

Before we jump into the code,
I want to show you a simple design of the clock and also provide a
class diagram depicting the classes used in the demo.
Below depicts a mockup of the parts
that comprise the arc clock:

Figure 3: A visual design mockup comprised of the
parts of a clock

Figure 3 describes the parts that comprise
our demo ‘arc clock’ consisting of the following: An arc
(ArcPiece), hours, minutes,
seconds and meridian respectively (from left to right). Now that we
visually understand what pieces make up an arc clock, let me show
you a class diagram listing all of the classes we need to capture
the requirements for the demo.Figure
4lists the four classes
used in this clock demo.

Figure 4: ArcClock Demo Class
Diagram

The left side of the class diagram in Figure 4
show two main classes used to draw a clock using arcs. The
ArcClockclass is a container-type
class which holds anywhere from zero to manyArcPieceinstances.
AnArcClockalso contains the clock’s
radius and diameter (bounding box width of the clock). The
individual arc objects xArcPiece)will contain the arc
attributes which will be later rendered onto the canvas with each
update and render cycle. In Figure 3,
theArcPieceBuilderclass (upper right) is a
convenience class that follows an object oriented
builder pattern.Using this
class provides an easy way to construct anArcPieceinstance in declarative
syntax style programming. This pattern enables the developer to
reduce boilerplate code and allows ad hoc parameters to be
specified (method chaining).

Table
1displays all the attributes
which describes anArcPiececlass:

Attribute

Data Type

Example

Description

x

double

0

Upper left x coordinate of the bounding box

y

double

0

Upper left y coordinate of the bounding box

w

double

200

Width of the bounding box surrounding clock

h

double

200

Height of the bounding box surrounding clock

startAngle

double

45

Starting angle of the arc in degrees measure

arcExtent

double

240

Extent angle in degrees measure

strokeWidth

double

5

The pixel thickness of the stroke of the arc line

pixelsToMove

double

1

Number of pixels to animate arc appearing to rotate

strokeColor

Color

Color.RED

The color of the stroke

clockwise

Boolean

true

Animate arc to move clockwise otherwise counter clockwise

Table 1: The attributes contained in the ArcPiece class

For brevity‘s sake, I felt it
was better to expose attributes aspublicandnotto implement getter and setter methods which are
similar to the Java bean specification (convention). Also, I chose
to use simple primitive data types instead of JavaFX Properties
APIs. Using primitives can help lower overhead (the need to bind
against many values). At some point, you may want to run the demo
with an embedded version of Java on a more constrained device such
asRaspberry Pi,BeagleBoard, etc.

Now that you know the attributes to draw and arc, let’s see
what it would look like.Figure
5depicts an arc drawn
using the attributes x, y, w, h, startAngle, arcExtent,
strokeColor, andArcType. For our demo, I have
hard-coded all the arcs to beArcType.OPEN.

Figure 5
shows the information of an arc as it is to be drawn on the
canvas.

Figure 5: Arc Anatomy

The listing below shows the code snippet used
to draw an arc onto theGraphicsContext.

The main driver or JavaFX Application which
runs our demo is housed in theTronClockDemoclass
(Listing 3). This main driver class contains
an
AnimationTimerinstance
which will periodically update the arc clock’s attributes and draw
the parts onto theGraphicsContextsurface.

The listing below shows the main driver
class, TronClockDemo.java, and launches the JavaFX
application:

Initially,
the application’s main method will launch the JavaFX application
thread via theApplication.launch()method. Once the
application thread is ready (postinit()method),
thestart()method gets invoked. To
see other lifecycle methods, go to the JavaDocs onApplicationclass. You’ll notice in
Listing 3 that all the action occurs in
thestart()method. This is where
anAnimationTimerinstance is created using
an anonymous inner class and started using theAnimationTimer.start()method. As each cycle
occurs, thehandle()method is invoked by the
JavaFX Application thread. When invoking thehandle()method, you’ll notice the
inbound parameter ‘now’ of typelongis the
current time in nanoseconds for one frame.

The body
of the handle() method will take the following
steps:

Update clock models (blue clock, green clock,
and red clock)

Clear screen

Draw blue clock

Save GraphicsContext state

Translate X coordinates to the right of the
blue clock

Draw the green clock

Translate X coordinates to the right of the
green clock

Draw the red clock

Restore or return to the last save
GraphicsContext state

The listing below shows the source code for a simple Java class,
which is responsible for containing an arc’s model.

This listing begins with the predefined colors that will be
used in our three demo clocks. The instance variables are the
following:longPiece,arcPieces,maxDiameter, andradius.Table
2describes the attributes
of an instance of anArcClockclass.

Attribute

Data Type

Example

Description

longPiece

ArcPiece

A single open arc drawn on the outer rim of the clock

arcPieces

ArcPiece

Many randomly drawn open arcs in the clock

maxDiameter

int

200

Width of the clock

radius

double

100

Half width of the clock

To create an instance of anArcClock,the constructor will call
many static methods to build random open arcs shapes with varied
start angles and extent angles. Another thing to point out is
theupdate()anddraw()methods which are used to
assist in the animation cycle (AnimationTimer). At each animation
cycle, the clock will update the model and render the arcs onto the
graphics context. In addition to rendering all the arc pieces for
the arc clock, theArcClockclass will also display
(draw) the time using theGraphicsContext’sfillText()method.

Well, there you have it, a quick glimpse of the JavaFX
Canvas API. Although we’ve only touched the surface of the
capabilities of the Canvas API, I have listed some of the other
interesting features of JavaFX 2.2 and the Canvas
API.

Snapshot – Any Scene graph node can
capture a node’s as a bitmap image.

Carl P. Dea is currently a Sr. Software Engineer, co-author of Java 7 Recipes, author of JavaFX 2 Introduction by Example, and technical reviewer of Pro JavaFX 2 from Apress publishing. Carl has been developing software for over 15 years with many clients from fortune 500 companies to nonprofit organizations. He has written software ranging from mission critical applications to e-commerce-based Web applications. Carl has been using Java since the very beginning and he also is a huge JavaFX enthusiast dating back when it used to be called F3. His current software development interests are: UI/UX, game programming, data visualization, microcontrollers, smart phones and tablet computers. When he's not working he and his wife love to watch their daughters perform at gymnastics meets. Carl lives on the East Coast in Pasadena, Maryland USA.