|
Playing with Shapes
The javafx.scene.geometry package includes an abstract Shape class that serves as the base class for various geometric shape subclasses (such as Circle, Line, and Path). Because this class subclasses Node, it inherits Node's attributes and functions, while introducing the following attributes of its own:
* fill (of type Paint) specifies this shape's background paint -- the default value is null.
* smooth (of type Boolean) specifies whether or not antialiasing hints are used for this shape -- the default value is true (use antialiasing hints).
* stroke (of type Paint) specifies this shape's outline paint -- the default value is null.
* strokeDashArray (of type Number[]) specifies a sequence representing the lengths of the dash segments. Alternate sequence entries represent the user space lengths of the opaque and transparent segments of the dashes. As the pen moves along the outline of this shape, the user space distance that the pen travels is accumulated. The distance value is used to index into the dash sequence. The pen is opaque when its current cumulative distance maps to an even element of the dash sequence, and transparent otherwise. The default value is [1.0] (a one-element sequence containing 1.0).
* strokeDashOffset (of type Number) specifies a distance in user coordinates that represents an offset into the dashing pattern -- the point in the dashing pattern that will correspond to the beginning of the stroke. The default value is 0.0.
* strokeLineCap (of type javafx.scene.geometry.StrokeLineCap) specifies the end cap style of this shape as one of StrokeLineCap.BUTT (end unclosed subpaths and dash segments with no added decoration), StrokeLineCap.ROUND (end unclosed subpaths and dash segments with a round decoration that has a radius equal to half of the width of the pen), and StrokeLineCap.SQUARE (end unclosed subpaths and dash segments with a square projection that extends beyond the end of the segment to a distance equal to half of the line width). The default value is StrokeLineCap.SQUARE.
* strokeLineJoin (of type javafx.scene.geometry.StrokeLineJoin) specifies the decoration applied where path segments meet as one of StrokeLineJoin.BEVEL (join path segments by connecting the outer corners of their wide outlines with a straight segment), StrokeLineJoin.MITER (join path segments by extending their outside edges until they meet), and StrokeLineJoin.ROUND (join path segments by rounding off the corner at a radius of half the line width). The default value is StrokeLineJoin.MITER.
* strokeMiterLimit (of type Number) specifies the limit for the StrokeLineJoin.MITER line join style -- the default value is 10.0.
* strokeWidth (of type Number) specifies a square pen line width -- the default value is 1.0.
Along with Circle, Line, and Path, and additional shape classes such as Arc, CubicCurve, Polygon, and Rectangle, javafx.scene.geometry provides PathElement. This abstract class is the base class for LineTo, MoveTo, and other classes that describe a Path's elements.
Let's play with some of these shape classes. Start NetBeans and use the New Project wizard to introduce a new APIDemo3 project with apidemo3.Shapes as the project's main file. Then replace the skeletal Shapes.fx's // place your code here line with the script in Listing 10.
Listing 10. Shapes.fx
/*
* Shapes.fx
*
*/
package apidemo3;
/**
* @author Jeff Friesen
*/
import java.lang.Math;
import java.lang.System;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.geometry.Arc;
import javafx.scene.geometry.ArcType;
import javafx.scene.geometry.Circle;
import javafx.scene.geometry.CubicCurve;
import javafx.scene.geometry.Ellipse;
import javafx.scene.geometry.Line;
import javafx.scene.geometry.QuadCurve;
import javafx.scene.geometry.Rectangle;
import javafx.scene.geometry.Shape;
import javafx.scene.paint.Color;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
class Model
{
attribute width: Integer;
attribute height: Integer;
attribute shape: Shape;
private attribute opacity: Number;
private function rnd (limit: Integer): Integer
{
Math.random ()*limit as Integer
}
private function arc (): Shape
{
Arc
{
centerX: rnd (width)
centerY: rnd (height)
radiusX: rnd (Math.min (width/2, height/2))
radiusY: rnd (Math.min (width/2, height/2))
startAngle: rnd (180)
length: rnd (180)
type: ArcType.ROUND
fill: Color.rgb (rnd (256), rnd (256), rnd (256))
opacity: bind opacity
}
}
private function circle (): Shape
{
Circle
{
centerX: rnd (width)
centerY: rnd (height)
radius: rnd (Math.min (width/2, height/2))
fill: Color.rgb (rnd (256), rnd (256), rnd (256))
opacity: bind opacity
}
}
private function cubicCurve (): Shape
{
CubicCurve
{
startX: rnd (width)
startY: rnd (height)
controlX1: rnd (width)
controlY1: rnd (width)
controlX2: rnd (width)
controlY2: rnd (width)
endX: rnd (width/2)
endY: rnd (height/2)
fill: Color.rgb (rnd (256), rnd (256), rnd (256))
opacity: bind opacity
}
}
private function ellipse (): Shape
{
Ellipse
{
centerX: rnd (width)
centerY: rnd (height)
radiusX: rnd (Math.min (width/2, height/2))
radiusY: rnd (Math.min (width/2, height/2))
fill: Color.rgb (rnd (256), rnd (256), rnd (256))
opacity: bind opacity
}
}
private function line (): Shape
{
Line
{
startX: rnd (width)
startY: rnd (height)
endX: rnd (width)
endY: rnd (height)
stroke: Color.rgb (rnd (256), rnd (256), rnd (256))
opacity: bind opacity
}
}
private function quadCurve (): Shape
{
QuadCurve
{
startX: rnd (width)
startY: rnd (height)
endX: rnd (width)
endY: rnd (height)
controlX: rnd (width)
controlY: rnd (height)
fill: Color.rgb (rnd (256), rnd (256), rnd (256))
opacity: bind opacity
}
}
function rectangle (): Shape
{
Rectangle
{
x: rnd (width)
y: rnd (height)
width: rnd (width)
height: rnd (height)
arcWidth: rnd (10)
arcHeight: rnd (10)
fill: Color.rgb (rnd (256), rnd (256), rnd (256))
opacity: bind opacity
}
}
private attribute shapes = [arc, circle, cubicCurve, ellipse, line,
quadCurve, rectangle];
private attribute timeline = Timeline
{
repeatCount: Timeline.INDEFINITE
keyFrames: for (i in [1..sizeof shapes])
{
KeyFrame
{
time: 3s*indexof i
action: function ()
{
shape = shapes [rnd (sizeof shapes)] ()
}
timelines:
[
Timeline
{
autoReverse: true
repeatCount: 2
var begin = at (0s)
{
opacity => 0.0
}
var end = at (1s)
{
opacity => 1.0 tween Interpolator.LINEAR
}
keyFrames: [begin, end]
}
]
}
}
}
attribute animate: Boolean on replace o=n
{
if (n == true)
timeline.start ()
else
timeline.stop ()
}
}
Frame
{
var model = Model
{
width: 300
height: 300
animate: true
}
title: "Shapes Tour"
width: bind model.width with inverse
height: bind model.height with inverse
stage: Stage
{
fill: LinearGradient
{
startX: 0.0
startY: 0.0
endX: 0.0
endY: 1.0
stops:
[
Stop { offset: 0.0 color: Color.YELLOW },
Stop { offset: 1.0 color: Color.CYAN }
]
}
content: bind [model.shape]
}
closeAction: function ()
{
model.animate = false;
System.exit (0)
}
visible: true
} |
|