Andres is a DZone Zone Leader and has posted 143 posts at DZone. You can read more from them at their website. View Full User Profile

GraphicsBuilder Tutorial I: Shapes

02.02.2008
| 28509 views |
  • submit to reddit

Drawing graphics with Java2D has never been an easy task, if it was we have probably seen by now a Flex killer app in Java (the fact that applets have a really bad press also contributed to not having that app). Let me introduce you to GraphicsBuilder, a Groovy builder for Java2D, while it alone is not the killer app, it surely can help you build one with less effort than doing it with straight Java.

Introduction

If you are still wondering what is Groovy and what is its relation to Java, I recommend you take a look at From Java to Groovy in a few easy steps and other articles you may find in this site. Back already? let's continue with the topic at hand. GraphicsBuilder is a builder for Java2D, which means that every node in the builder represents an action that will affect a Graphics2D object, the same type of object Swing uses to draw components on the screen. To get you started you should have Groovy installed in your computer as well as the latest GraphicsBuilder distribution (0.4.5 at the time of this writing), if you are on windows using the installer makes it pretty trivial as graphicsbuilder comes bundled with it.

If you have played around with Groovy for a while you surely have come across with a handy tool named groovyConsole, a visual shell that evaluates groovy scripts, well GraphicsBuilder includes a similar tool named graphicsPad that will let you write and run groovy scripts for drawings. All of the code samples you will see on this tutorial can be executed on graphicsPad, the tool also has an option to export your scripts into standalone scripts, which can be run from the command line or with groovyConsole itself.

Basic Shapes

Java2D provides a small set of basic shapes which mostJava based graphic tools support, GraphicsBuilder does the same, the following image shows a sample of those shapes


Let's see, we have rectangles (angular and rounded), circles, ellipses, arcs, polygons and paths. Arcs may have 3 different closing modes and paths may have 2 different winding values, that is why the last star has a hole in the middle. Now let's take a look at the code that produced this image

rect( x: 10, y: 10, width: 50, height: 50, borderColor: 'black', fill:'red' )
rect( x: 70, y: 10, width: 50, height: 50, arcWidth: 20, arcHeight: 20,
borderColor: 'black', fill:'orange' )
circle( cx: 155, cy: 35, radius: 25, borderColor: 'black', fill: 'darkGreen' )
ellipse( cx: 225, cy: 35, radiusx: 35, radiusy: 25, borderColor: 'black', fill: 'blue' )
arc( x: -40, y: 70, width: 100, height: 100, start: 0, extent: 90,
borderColor: 'black', fill: 'cyan', close: 'pie' )
arc( x: 20, y: 70, width: 100, height: 100, start: 0, extent: 90,
borderColor: 'black', fill: 'magenta', close: 'chord' )
arc( x: 80, y: 70, width: 100, height: 100, start: 0, extent: 90,
borderColor: 'black', fill: 'yellow', close: 'open' )
polygon( points: [190,70,225,90,260,70,250,120,225,110,200,120],
borderColor: 'black', fill: 'black' )
path( borderColor: 'black', fill: 'purple', winding: 'nonzero' ){
moveTo( x: 40, y: 130 )
lineTo( x: 20, y: 200 )
lineTo( x: 70, y: 158 )
lineTo( x: 10, y: 158 )
lineTo( x: 60, y: 200 )
close()
}
path( borderColor: 'black', fill: 'lime', winding: 'evenodd' ){
moveTo( x: 120, y: 130 )
lineTo( x: 100, y: 200 )
lineTo( x: 150, y: 158 )
lineTo( x: 90, y: 158 )
lineTo( x: 140, y: 200 )
close()
}

You will notice that all shapes share similar properties, like borderColor and fill, that colors are defined as strings (but there are more powerful ways to get a custom color, we will see that on a later tutorial) following the css2 color set. The most complex shape so far is path because each segment must be constructed with a path operation, all path operations are defined in GeneralPath/Path2D so their names are pretty straightforward.

Extended Path

GraphicsBuilder supports an extended version of path, provided by Batik project (graphicsbuilder-ext-svg and batik libraries are required in the classpath), the main difference is that xpath has an xarcTo operation capable of drawing arcs as opposed to curves only.

Note that you can not mix path and xpath operations in the same path.

xpath( borderColor: 'darkRed', fill: 'red', borderWidth: 4 ){
xmoveTo( x: 10, y: 10 )
xhline( x: 160 )
xvline( y: 60 )
xarcTo( x: 10, y: 60, rx: 150, ry: 150, angle: 90, sweep: true, largeArc: false )
xclose()
}
xpath( borderColor: 'darkRed', fill: 'red', borderWidth: 4 ){
xmoveTo( x: 170, y: 10 )
xhline( x: 320 )
xvline( y: 60 )
xarcTo( x: 170, y: 60, rx: 150, ry: 150, angle: 90, sweep: false, largeArc: false )
xclose()
}

Published at DZone with permission of its author, Andres Almiray.

Comments

Christopher Brown replied on Mon, 2008/02/04 - 3:45am

Hi Andres,

How does this relate to https://scenegraph.dev.java.net/ ?

I'm assuming that with the Groovy graphics builder, you would need to use the builder on every UI repaint to completely repaint the image.  The scene graph API aims to create shapes that stay defined in memory between repaints, a bit like SVG without the XML, so with the SGAPI you define your circle once then have the choice of manipulating it through time.

Other questions: if not SGAPI-compatible, is there clipping support for the groovy graphics (i.e.: ways of making it easier to deal with) so that you don't waste time drawing shapes outside of the painting area?

Thanks,

Chris 

Mahesh Kumar Nayak replied on Fri, 2011/05/20 - 3:48pm

Hi,

I do complite agree with Christopher.

http://www.glinthost.com

Andres Almiray replied on Mon, 2008/02/04 - 12:44pm in response to: Christopher Brown

Chris, GraphicsBuilder and SceneGraph share many traits but they are essentially two different and unrelated implementations. When I saw the announcement of SceneGraph my first reaction was to rework GraphicsBuilder to support it but because their API is still in flux I refrained to do so. Perhaps when their API goes to 1.0 GraphicsBuilder will be able to export/import SGAPI code, that would be great.

On the UI repaint, it depends on what you are trying to accomplish, GB includes a basic component where you can place your drawings: GraphicsPanel. This component is smart enough to redraw whenever it needs to, and only those places that have actually changed, which means it honors the clip. All shapes take into consideration the curret clip, no need to waste cycles, there is also an option to specify custom clips with the clip() node. You can also render to images directly and use your own cache mechanism.

GB can also reuse shape definitions, either with a normal Groovy variable or with an special 'asShape' property which I didn't show in this tutorial, but now that the topic has surfaced I will make sure it is included in the next part.

If you care to know more about GraphicsBuilder before I finish the other parts of the tutorial, please visit the project's site, you will also find more info at my blog, you'll see that GB has more to offer that what has been shown so far here. 

Cheers,
Andres

Andres Almiray replied on Mon, 2008/02/04 - 12:48pm in response to: Christopher Brown

You may also find this link useful, the images are snapshots of GraphicsPanel in action, a custom clip has been set (so that the radial lines do not extend beyond the rounded rectangle), you will also see other options as paints (and multipaints, a unique feature so far).

Cheers,
Andres

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.