About Andreas Pomarolli

Andreas has graduated from Computer Science and Bioinformatics at the University of Linz. During his studies he has been involved with a large number of research projects ranging from software engineering to data engineering and at least web engineering. His scientific focus includes the areas of software engineering, data engineering, web engineering and project management. He currently works as a software engineer in the IT sector where he is mainly involved with projects based on Java, Databases and Web Technologies.

JavaFX Complex Shape Example

This is a JavaFX Complex Shape Example. You can draw complex shapes using the Path class. An instance of the Path class defines the path (outline) of a shape. A path consists of one or more subpaths. A subpath consists of one or more path elements. Each subpath has a starting point and an ending point.

A path element is an instance of the PathElement abstract class. The following subclasses of the PathElement class exist to represent specific type of path elements:

MoveTo

LineTo

HLineTo

VLineTo

ArcTo

QuadCurveTo

CubicCurveTo

ClosePath

The Path class contains three constructors:

Path()

Path(Collection elements)

Path(PathElement… elements)

The no-args constructor creates an empty shape. The other two constructors take a list of path elements as arguments.

A Path stores path elements in an ObservableList<PathElement>. You can get the reference of the list using the getElements() method. You can modify the list of path elements to modify the shape.

1.2 The MoveTo Path Element

A MoveTo path element is used to make the specified x and y coordinates as the current point. It has the effect of lifting and placing the pencil at the specified point on the paper.

The first path element of a Path object must be a MoveTo element and it must not use relative coordinates. The MoveTo class defines two double properties that are the x and y coordinates of the point.

x

y

The MoveTo class contains two constructors. The no-args constructor sets the current point to (0.0, 0.0). The other constructor takes the x and y coordinates of the current point as arguments.

// Create a MoveTo path element to move the current point to (0.0, 0.0)
MoveTo mt1 = new MoveTo();
// Create a MoveTo path element to move the current point to (10.0, 10.0)
MoveTo mt2 = new MoveTo(10.0, 10.0);

1.3 The LineTo Path Element

A LineTo path element draws a straight line from the current point to the specified point. It contains two double properties that are the x and y coordinates of the end of the line:

x

y

The LineTo class contains two constructors. The no-args constructor sets the end of the line to (0.0, 0.0). The other constructor takes the x and y coordinates of the end of the line as arguments.

// Create a LineTo path element with its end at (0.0, 0.0)
LineTo lt1 = new LineTo();
// Create a LineTo path element with its end at (10.0, 10.0)
LineTo lt2 = new LineTo(10.0, 10.0);

With the knowledge of the MoveTo and LineTo path elements, you can construct shapes that are made of lines only.

1.4 The ClosePath Path Element

The ClosePath path element closes the current subpath. Note that a Path may consist of multiple subpaths, and, therefore, it is possible to have multiple ClosePath elements in a Path. A ClosePath element draws a straight line from the current point to the initial point of the current subpath and ends the subpath.

A ClosePath element may be followed by a MoveTo element, and in that case, the MoveTo element is the starting point of the next subpath.

If a ClosePath element is followed by a path element other than a MoveTo element, the next subpath starts at the starting point of the subpath that was closed by the ClosePath element.

You can rewrite the path for the previous triangle example using a ClosePath.

2.2 The HLineTo Path Element

The HLineTo path element draws a horizontal line from the current point to the specified x coordinate. The y coordinate of the ending point of the line is the same as the y coordinate of the current point. The x property of the HLineTo class specifies the x coordinate of the ending point.

// Create an horizontal line from the current point (x, y) to (50, y)
HLineTo hlt = new HLineTo(50);

2.3 The VLineTo Path Element

The VLineTo path element draws a vertical line from the current point to the specified y coordinate. The x coordinate of the ending point of the line is the same as the x coordinate of the current point. The y property of the VLineTo class specifies the y coordinate of the ending point.

// Create a vertical line from the current point (x, y) to (x, 50)
VLineTo vlt = new VLineTo(50);

The following snippet of code creates the same triangle as discussed in the previous section. This time, you use HLineTo and VLineTo path elements to draw the base and height sides of the triangle instead of the LineTo path elements.

Path triangle = new Path(new MoveTo(0, 0),
new VLineTo(50),
new HLineTo(50),
new ClosePath());

2.4 The ArcTo Path Element

An ArcTo path element defines a segment of ellipse connecting the current point and the specified point.

It contains the following properties:

radiusX

radiusY

x

y

XAxisRotation

largeArcFlag

sweepFlag

The radiusX and radiusY properties specify the horizontal and vertical radii of the ellipse.

The x and y properties specify the x and y coordinates of the ending point of the arc. Note that the starting point of the arc is the current point of the path.

The XAxisRotation property specifies the rotation of the x-axis of the ellipse in degrees. Note that the rotation is for the x-axis of the ellipse from which the arc is obtained, not the x-axis of the coordinate system of the node. A positive value rotates the x-axis counterclockwise.

The largeArcFlag and sweepFlag properties are Boolean type, and by default, they are set to false.

The following code snippet creates a path with an ArcTo path element:

// Create the ArcTo path element
arcTo = new ArcTo();
// Use the arcTo element to build a Path
Path path = new Path(new MoveTo(0, 0),
new VLineTo(100),
new HLineTo(100),
new VLineTo(50),
arcTo);

2.5 The GUI

The above program uses an ArcTo path element to build a Path object. The program lets the user change properties of the ArcTo path element:

The coordinates defining a PathElement can be absolute or relative. By default, coordinates are absolute. It is specified by the absolute property of the PathElement class. If it is true, which is the default, the coordinates are absolute. If it is false, the coordinates are relative. The absolute coordinates are measured relative to the local coordinate system of the node. Relative coordinates are measured treating the ending point of the previous PathElement as the origin.

3.2 The Fill Rule for a Path

A Path can be used to draw very complex shapes. Sometimes, it is hard to determine whether a point is inside or outside the shape. The Path class contains a fillRule property that is used to determine whether a point is inside a shape.

Its value could be one of the constants of the FillRule enum: NON_ZERO and EVEN_ODD. If a point is inside the shape, it will be rendered using the fill color.

The direction of the stroke is the vital factor in determining whether a point is inside a shape. The fill rule of a Path draws rays from the point to infinity, so they can intersect all path segments.

In the NON_ZERO fill rule, if the number of path segments intersected by rays is equal in counterclockwise and clockwise directions, the point is outside the shape. Otherwise, the point is inside the shape. You can understand this rule by using a counter, which starts with zero. Add one to the counter for every ray intersecting a path segment in the counterclockwise direction.

Subtract one from the counter for every ray intersecting a path segment in the clockwise direction. At the end, if the counter is non-zero, the point is inside. Otherwise, the point is outside.

Like the NON_ZERO fill rule, the EVEN_ODD fill rule also draws rays from a point in all directions extending to infinity, so all path segments are intersected. It counts the number of intersections between the rays and the path segments. If the number is odd, the point is inside the path. Otherwise, the point is outside the path.

The following code snippet creates thow paths with the fill rule EVEN_ODD.

The Shape class provides three static methods that let you perform union, intersection and subtraction of shapes.

union(Shape shape1, Shape shape2)

intersect(Shape shape1, Shape shape2)

subtract(Shape shape1, Shape shape2)

The methods return a new Shape instance. They operate on the areas of the input shapes. If a shape does not have a fill and a stroke, its area is zero. The new shape has a stroke and a fill.

The union() method combines the areas of two shapes. The intersect() method uses the common areas between the shapes to create the new shape. The subtract() method creates a new shape by subtracting the specified second shape from the first shape.

Stroking is the process of painting the outline of a shape. Sometimes, the outline of a shape is also known as stroke. The Shape class contains several properties to define the appearance of the stroke of a shape.

stroke

strokeWidth

strokeType

strokeLineCap

strokeLineJoin

strokeMiterLimit

strokeDashOffset

The stroke property specifies the color of the stroke. The default stroke is set to null for all shapes except Line, Path and Polyline, which have Color.BLACK as their default stroke.

The strokeWidth property specifies the width of the stroke. It is 1.0px by default. The stroke is painted along the boundary of a shape.

The strokeType property specifies the distribution of the width of the stroke on the boundary. Its value is one of the three constants, CENTERED, INSIDE, and OUTSIDE, the StrokeType enum. The default value is CENTERED. The CENTERED stroke type draws a half of the stroke width outside and half inside the boundary. The INSIDE stroke type draws the stroke inside the boundary. The OUTSIDE stroke draws the stroke outside the boundary. The stroke width of a shape is included in its layout bounds.

The strokeLineCap property specifies the ending decoration of a stroke for unclosed subpaths and dash segments. Its value is one of the constants of the StrokeLineCap enum: BUTT, SQUARE, and ROUND. The default is BUTT. The BUTT line cap adds no decoration to the end of a subpath; the stroke starts and ends exactly at the starting and ending points. The SQUARE line cap extends the end by half the stroke width. The ROUND line cap adds a round cap to the end. The round cap uses a radius equal to half the stroke width.

The strokeLineJoin property specifies how two successive path elements of a subpath are joined. Its value is one of the constants of the StrokeLineJoin enum: BEVEL, MITER, and ROUND. The default is MITER. The BEVEL line join connects the outer corners of path elements by a straight line. The MITER line join extends the outer edges of two path elements until they meet. The ROUND line join connects two path elements by rounding their corners by half the stroke width.

If the path elements meet at a smaller angle, the length of the join may become very big. You can limit the length of the join using the strokeMiterLimit property. It specifies the ratio of the miter length and the stroke width. The miter length is the distance between the most inside point and the most outside point of the join. If the two path elements cannot meet by extending their outer edges within this limit, a BEVEL join is used instead. The default value is 10.0. That is, by default, the miter length may be up to ten times the stroke width.

By default, the stroke draws a solid outline. You can also have a dashed outline. You need to provide a dashing pattern and a dash offset. The dashing pattern is an array of double that is stored in an ObservableList<Double>. You can get the reference of the list using the getStrokeDashArray() method of the Shape class. The elements of the list specify a pattern of dashes and gaps. The first element is the dash length, the second gap, the third dash length, the fourth gap, and so on. The dashing pattern is repeated to draw the outline. The strokeDashOffset property specifies the offset in the dashing pattern where the stroke begins.

The following code snippet creates a lightgray Rectangle with a black Stroke and a strokeWidth of 4px.

5.2 The GUI

The above program creates four rectangles as shown in the following image. All rectangles have the same width and height.

The first rectangle, counting from the left, has no stroke and it has layout bounds of 50px X 50px. The second rectangle uses a stroke of width 4px and an INSIDE stroke type. The third rectangle uses a stroke width 4px and a CENTERED stroke type, which is the default. The fourth rectangle uses a 4px stroke width and an OUTSIDE stroke type.

Newsletter

Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

Email address:

Receive Java & Developer job alerts in your Area

Leave this field empty if you're human:

Join Us

With 1,240,600 monthly unique visitors and over 500 authors we are placed among the top Java related sites around. Constantly being on the lookout for partners; we encourage you to join us. So If you have a blog with unique and interesting content then you should check out our JCG partners program. You can also be a guest writer for Java Code Geeks and hone your writing skills!

Disclaimer

All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners. Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. Examples Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.