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 II: Outlines & Shapes

  • submit to reddit

The Missing Shapes

Even though GraphicsBuilder packs many shapes, more than the basic ones that Java2D provides, not counting the ability to create your own shapes using area operations, there are two other shapes you may use: text and morph. Drawing text requires setting a font (unless you want to use the default settings), fonts require at least one of the following properties: face, size, style. Or you can set any java.awt.Font instance available. The following example shows 4 text shapes, each with a different value for it's font's style and size. Notice that the font definition is nested inside the text node, that way it will only be applied to that shape in particular. If for any reason you define a font outside a text node, then all subsequent text nodes will use that font.

def colors = ['red','orange','darkGreen','blue']
def sizes = [24,36,48,60]
def offsets = [48,80,48,60]
def styles = ['plain','bold','italic','bold|italic']
(0..3).each { n ->
text( text: 'GROOVY', x: 10, y: 0 +(sizes[n]*(n+1)/2),
fill: colors[n], borderColor: 'black' ){
font( size: sizes[n], style: styles[n] )

You can use any combination of the Font.* constants to set the style, or go with the literal option, using a pipe '|' char to separate each token. The second shape comes from the Swingx project, it morphs two shapes into a third one, allowing you to control how much of both shapes contribute to the final one with a morph property; the more the value is close to 0 it will look to the first shape, conversely the more that value is close to 1 it will look like the second shape.

So we have two shapes, a rectangle and start posing as the first and second shapes, then we have a third shape that resembles the rectangle and a fourth one that resembles the star. Let's see the code

def rect = rect( x: 20, y: 50, width: 100, height: 100, arcWidth: 20, 
arcHeight: 20, asShape: true )
def star = star( cx: 100, cy: 100, ir: 50, or: 80, count: 5, asShape: true )

morph( start: rect, end: star, morph: 0.0, borderWidth: 3,
borderColor: 'orange', fill: 'yellow' ){
transformations { translate(x: 0, y: 0) }
morph( start: rect, end: star, morph: 1.0, borderWidth: 3,
borderColor: 'blue', fill: 'cyan' ){
transformations { translate(x: 140, y: 0) }
morph( start: rect, end: star, morph: 0.3, borderWidth: 3,
borderColor: 'orange', fill: 'yellow' ){
transformations { translate(x: 20, y: 150) }
morph( start: rect, end: star, morph: 0.7, borderWidth: 3,
borderColor: 'blue', fill: 'cyan' ){
transformations { translate(x: 140, y: 150) }


What is going here? we have clearly 6 shape definitions but only 4 are being drawn. It turns out that shapes (and outlines too) share a property named asShape, when set to true (or on or yes) it will tell GraphicsBuilder not to draw the shape but create the operation only, that way you will be able to reuse the shape or outline definition as many times as you want and in as many places as you need. The code clearly shows that setting the morph value to 0 will draw the first shape unchanged, the same thing happens to the second shape if set to 1. You will notice that all 4 shapes have a transformation/translate node applied, we will look further into transformations at a later installment of this series, but suffices to say that translate moves a shape around to the coordinates you specify.

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