How-To's > How do I work with shapes?
Shapes and the elements related to them are part of the javafx.scene.shape.Shape class, which provides variables to create the stroke and fill of the shape, among other variables. All shapes inherit from the Node class.
See the following topics for more information about working with shapes.
- Create a line
- Create a rectangle or square
- Create a diamond
- Create a circle
- Create an ellipse
- Create a polygon
- Create a nonstandard shape
- Create a morphing effect from one shape to another
- Clip shapes
Related How-To Topics and Tutorials
- Work with stroke and fill
- Create a drop shadow
- Create a linear gradient
- Create a radial gradient
- Add a reflection
- Add a glow
- Work with text
- Change an object's size
- Use nodes
- Building GUI Applications With JavaFX Lesson 1: Quick JavaFX GUI Overview
The Shapes section demonstrates the types of shapes that can be drawn with specific classes. Other parts of the tutorial provide information about how to create specific shapes.
API Documentation
How do I create a line?
Lines are a type of shape in the JavaFX Script programming language, and, as such, you can use several different shape classes to create them, depending on the type of line you want.
Single Straight Line
The Line class can be used for straight line segments in (x,y) coordinate space. You define the starting coordinates and ending coordinates of the line, as in the following example:

import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
Stage {
title: "line"
style: StageStyle.UNDECORATED
scene: Scene {
fill:Color.GRAY
width: 100
height: 100
content: [
Line {
startX: 0 startY: 0
endX: 100 endY: 100
stroke:Color.ORANGE
strokeWidth:3
}
]
}
}
Note: The default stage style is DECORATED. Decorated windows are always subject to minimum sizes, as determined by the window system. In the previous example, the window size is wider at runtime than the width set for the scene, and the line will not end in the bottom right corner, as you might expect. Minimum decorated window sizes apply to desktop and Web Start applications, not to browser applets.
Series of Connected Straight Lines
The Polyline class constructs a series of x, y coordinates to mark the horizontal and vertical position of each point. Lines are connected automatically between each consecutive set of points. Unlike polygons, the last line is not connected with the first line.
Here is an example of a polyline arrow.

Polyline {
points: [
10.0, 45.0,
55.0, 45.0,
50.0, 20.0,
92.0, 50.0,
50.0, 80.0,
55.0, 55.0,
10.0, 55.0,
]
stroke:Color.DARKGREEN;
strokeWidth:6;
fill:Color.FORESTGREEN;
}
Curved Line
You can create curved lines in several ways:
- Use the
CubicCurveandQuadCurveclasses to create cubic and quadratic Bezier curves respectively. See the API documentation for code examples. - Use the
Pathclass to create connected curved lines. See How do I create a nonstandard shape? - The
ShapeSubtractorShapeIntersectclasses can be used to create shapes by subtraction or intersection. ou can use these classes to create a curve from part of a circle or ellipse. See the API documentation for code examples.
Tips
- For rendering wide lines, use the
Rectangleclass instead of theLineclass, or use theLineclass with thestrokeWidthvariable. TheRectangleclass is the better option for performance reasons. - If you want a line to have different colors of fill and stroke, use the
Rectangleclass, because theLineclass does not have an interior. - Lines inherit variables that control animation and effects from
javafx.scene.Node. See the topics about animation and effects for more information.
Examples
- Bezier Curve Animation
Describes and demonstrates Bezier curves created with the theQuadCurveandCubicCurveclasses. - Media Browser Module 3 Task 2: Adding a Text Control
The section "Drawing a Horizontal Line" shows how to use thePathclass to draw horizontal lines.
API Documentation
How do I create a rectangle or square?
Create a rectangle or square by using the Rectangle class.
Use the following variables to determine the size, shape, and position of the rectangle or square:
width– The width of the rectangleheight– The height of the rectanglex– The horizontal position in the scene graph of the upper left corner of the rectangle, where the value 0 is the leftmost pixely– The vertical position in the scene graph of the upper left corner of the rectangle, where the value 0 is the topmost pixel
Example Code

Rectangle {
x: 10
y: 30
height: 40
width:40
fill: Color.web("#1F6592")
}
Tips
- To create a square, make the values for height and width the same.
- To create a rectangle with rounded corners, use the
arcHeightandarcWidthvariables, which control the degree of rounding. The default is 0.0 for no rounding. If the value forarcHeightandarcWidthis the same as or greater than a square's height and width respectively, the shape appears as a circle. - If you add a stroke to a rectangle, using the
strokeandstrokeWidthvariables inherited from theShapeclass, the stroke is added to the outside of the boundaries of the rectangle set byheightandwidth. - Because rectangles are nodes, you can apply animations and effects to them, including drop shadows.
Examples
API Documentation
How do I create a diamond?
The easiest way to create a diamond is to create a square and use the rotate variable, inherited from the Node class, to rotate it 45 degree.
Example Code
The screen capture on the left shows the code without the rotate variable. The screen capture on the right shows the same code with the rotate variable set to 45 degrees. Note that the rotation point is the center of the object.

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.Color;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Line;
Stage {
title: "Diamond"
width: 300
height: 200
scene: Scene {
content: [
Rectangle {
translateX:50
translateY:50
width: 50
height: 50
fill:
RadialGradient {
stops: [
Stop {
color : Color.web("#80CAFA")
offset: 0.0
}
Stop {
color : Color.web("#1F6592")
offset: 1.0
}
]
}
rotate:45
}
Line {
startX: 50
startY:20
endX:50
endY:140
}
Line {
startX: 20
startY: 50
endX: 140
endY: 50
}
]
}
}
Tips
- The rotation factor in
Node.rotateis not included inlayoutBounds, which makes therotatevariable ideal for rotating the entire node after all effects and transforms have been applied. - You can specify a pivot point by using the rotation transformation instead of
Node.rotate. For more information about the rotation transformation, see the topic How do I rotate objects?
API Documentation
How do I create a circle?
Create a circle by using the Circle class.
Use the following variables to determine the size and position of the circle:
radius– The radius of the circle (from the center of the circle to the edge)centerX– The horizontal position in the scene graph of the center of the circle, where the value 0 is the leftmost pixelcenterY– The vertical position in the scene graph of the center of the circle, where the value 0 is the topmost pixel
To create stroke and fill for the circle, see the topic How do I work with fills and strokes?
Example Code

Circle {
centerX: 192 centerY: 174
radius: 30
fill:Color.DARKORANGE
stroke:Color.ORANGERED
strokeWidth:1
}
Tips
- Because circles inherit variables from the
Shapeclass andNodeclass, you can apply animations and effects to them, including drop shadows.
Examples
API Documentation
How do I create an ellipse?
Create an ellipse by using the Ellipse class.
Use the following variables to determine the size, shape, and position of the ellipse:
radiusX– The width of the ellipse from its center to its edge, in pixelsradiusY– The height of the ellipse from its center to its edge, in pixelscenterX– The horizontal position in the scene graph of the center of the ellipse, where the value 0 is the leftmost pixelcenterY– The vertical position in the scene graph of the center of the ellipse, where the value 0 is the topmost pixel
Example Code

Ellipse {
centerX: 100
centerY: 50
radiusX: 80
radiusY: 30
fill: Color.web("#1F6592")
}
Tips
- Because ellipses inherit variables from the
Shapeclass andNodeclass, you can apply animations and effects to them, including drop shadows. - You can also create an ellipse by using the
Rectangleclass and setting thearcHeightandarcWidthvariables to the same value as theheightandwidthrespectively. This strategy would be useful if you wanted to dynamically transform an ellipse into a rectangle or the reverse.
Examples
- JavaFX Coffee Cup
Contains code for several ellipses with a gradient fill.
API Documentation
How do I create a polygon?
Create a polygon by using the Polygon class. A polygon has as many straight sides as you want to create.
Polygons are constructed with a series of x, y coordinates to mark the horizontal and vertical position of each point. Lines are connected automatically between each consecutive set of points, and the last point in the list is connected to the first point automatically.
Example Code
The following code produces a polygon that has its lines crossing, with the following result. The red lines show the lines that are drawn between each two points.

Polygon {
points: [
10.0, 10.0, //the first coordinate is x, the second is y
40.0, 40.0,
10.0, 100.0,
40.0, 120.0
]
}
To create stroke and fill for the polygon, see the topic How do I work with fills and strokes?
Tips
- Because the
Polygonclass inherits variables from theShapeclass andNodeclass, you can apply animations and effects to them, including drop shadows. - If you don't want to connect the last point with the first point, use the
Polylineclass.
Examples
- Building GUI Applications With JavaFX Lesson 4: Creating Graphical Objects
Contains an example of using thePolygonclass to construct a triangle. - Creating a custom fill in JavaFX

Contains an example of a star shape. - 3-D Display Shelf With the PerspectiveTransform
Shows how to create four-sided polygons that change shape, using thePerspective transform.
API Documentation
How do I create a nonstandard shape?
You can create nonstandard shapes in several ways:
- Use the
Pathclass to create a shape of as many lines and curves as you like. You can even create gaps in a line. - Subtract one shape from another or use the intersections of two shapes, using the
ShapeSubtractorShapeIntersectclass respectively. - Use the
SVGPathclass to create a simple shape that is constructed by parsing SVG path data from a string. With this class, you can draw a path with a drawing tool that produces SVG-format files, then copy and paste the SVG path to reproduce the shape in JavaFX Script.
The remainder of this topic will focus on the Path class.
The Path class uses a positions variable to construct the coordinates and the components of the shape.
You can use any of the following classes as components of the shape.
Straight Lines
HLineTo– Creates a horizontal line from the current point tox(HLineTo API)VLineTo– Creates a vertical line from the current point toy(VLineTo API)LineTo– Draws a straight line from the current coordinate to the new coordinates (LineTo API)
Curves
ArcTo– Forms an arc from the previous coordinates to the specified x and y coordinates by using the specified radius. (ArcTo API)CubicCurveTo– Creates a cubic Bézier curve, which requires three intermediate Bézier control points. The curve intersects both the current coordinates and the specified coordinates (x,y), using the specified points (controlX1,controlY1) and (controlX2,controlY2). All coordinates are specified in double precision. (CubicCurveTo API)QuadCurveTo– Creates a quadratic Bézier curve, which requires two intermediate Bézier control points. The curve intersects both the current coordinates and the specified coordinates (x, y), using the specified point (controlX, controlY). All coordinates are specified in double precision. (QuadCurveTo API)
Other Components
MoveTo– Moves to the specified coordinates without creating a line. TheMoveToclass is used to create the starting point of the path. Used in the middle of the list of path points, it creates a gap in the line and is considered a new starting point byClosePath. (MoveTo API)ClosePath– Connects the current point to the last starting point. (ClosePath API)
Example Code
The following graphic provides an example of every class that can be used in the points variable. The code, which appears below the graphic, uses a single Path instance, yet the continuity of the line is broken by inserting a MoveTo instance in the middle of the list of points. Each number in red in the graphic corresponds to the number at the beginning of each comment line in the code.

The following code example shows how the path was created.
Path {
elements: [
//1 Starting point:
MoveTo { x: 50 y: 10 }
//2 Vertical line:
VLineTo { y: 50 }
//3 Norizontal line:
HLineTo { x: 100 }
//4 Line connecting previous to current points:
LineTo { x: 150 y: 100}
//5 Arc of radius 50:
ArcTo { x: 200 y: 150 radiusX: 50 radiusY: 50 }
//6 Gap in the line and a new starting point:
MoveTo {x: 250 y: 200 }
//7 Cubic Bezier curve:
CubicCurveTo {
controlX1: 250 controlY1: 250
controlX2: 300 controlY2: 300
x: 350 y: 250
}
//8 Quadratic Bezier curve:
QuadCurveTo {
controlX: 525.0 controlY: 550.0
x: 500.0 y: 100.0
}
//9 Connect to the most recent MoveTo instance
ClosePath{ }
]
fill:Color.BLUE;
}
Tips
- To create stroke and fill for the shape, see the topic How do I work with files and strokes? The default fill value is null instead of black for the
Pathclass. In the preceding graphic, afillvariable is specified. Note how the fill works in the part of the path that is not closed. The side with the smaller angles between each two points is filled. - The
QuadCurveandCubicCurveclasses can be used instead ofPathto define open Bezier curves. - The
Pathclass can also be used to draw lines. - A
PathorSVGPathobject or any other shape can be used with thePathTransitionclass to create animation along a path.
Examples
- Animation Along an Arbitrary Path
Animating Shapes Along a Path
Both the tech tip and sample show how to animate an object along a path. The tech tip uses a cubic Bezier curve, which is created with an instance of thePathclass andCubicCurveToto set the points. The sample uses instances ofLineTo,CubicCurveTo, andQuadCurveToto set the points. - Creating a Drawing Application in 5 Minutes
Full Screen Sketching
Both the tech tip and sample demonstrate a sketching application, which works by creating aPathinstance and points based on mouse clicks and movement. - Bezier Curve Animation
Describes and demonstrates Bezier curves created with the theQuadCurveandCubicCurveclasses, rather than theQuadCurveToandCubicCurveToclasses used in thepathcommand. - Jigsaw Created With Boolean Shape Operations
Shows how to use theShapeSubtractclass to create nonstandard shapes for jigsaw puzzle pieces. - Speedometer Draws on Public Attributes
Shows how to use theShapeSubtractclass to create different fill colors for various arcs within the display dial of a speedometer. - Media Browser Module 3 Task 2: Adding a Text Control
The section "Drawing a Horizontal Line" shows how to use thePathclass to draw horizontal lines.
API Documentation
How do I create a morphing effect from one shape to another?
Use the DelegateShape class to create a morphing effect from any shape to any other shape.
Example Code
The following code example shows how to use a morphing effect to change a rectangle to a circle and back again.

import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.DelegateShape;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
import javafx.scene.Scene;
var shape1 = Rectangle { x: 10 y: 10 width: 100 height: 50 };
var shape2 = Circle { centerX: 40 centerY: 40 radius: 20 };
var geom : Shape = shape1;
Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: true
keyFrames: [
KeyFrame { time: 0s values: geom => shape1 }
KeyFrame { time: 2s values: geom => shape2
tween Interpolator.LINEAR }
]
}.play();
Stage {
scene: Scene {
height:70
width:70
content:
DelegateShape {
shape: bind geom
fill: Color.web("#80CAFA")
}
}
}
API Documentation
How do I clip shapes?
Use the clip variable of the Node class to create a clipping path to restrict the display area of another shape. Any node can be used as a clipping path, which is applied to the node. Only the pixels of the main node that lie inside the clipping path are displayed.
Clipping is particularly useful when modifying the shape of an image. For example, suppose that a text object is used as a clipping path for an image node, the only parts of the image that are displayed are the parts that lie within the boundaries of the letters in the text string.
Example Code 1: Image With Rounded Corners
In the following example, a typical photo with square corners is clipped by a rounded rectangle of the same size, resulting in a photo with rounded corners.

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.shape.Rectangle;
// Import the image
def image = Image {
url: "{__DIR__}Vacation.jpg"
}
// The clipping node: text above a rectangle
def clipnode =
Rectangle {
x: 20
y: 20
height: image.height
width: image.width
arcHeight: 40
arcWidth: 40
}
// Display the image with the clipping node
def clippedimage = ImageView {
image: image
x: 20
y: 20
clip: clipnode
}
Stage {
title: "Clipping"
width: image.width + 40
height: image.height + 70
scene: Scene {
content: [
clippedimage
]
}
}
Example Code 2: Image Clipped by a Group Node
In the following example, the image is imported with an Image class instance and displayed in an ImageView node. The ImageView node is clipped by a Group node, which contains text and a rounded rectangle. The application produces the following clipped image:

A background rectangle is added to provide contrast for the clipped image:

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextOrigin;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.Group;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.FontWeight;
import javafx.scene.paint.Color;
// Import the image
def image = Image {
url: "{__DIR__}Vacation.jpg"
}
// The clipping node: text above a rectangle
def gp = Group {
content: [ Text {
content: "vacation"
textOrigin: TextOrigin.TOP
textAlignment: TextAlignment.CENTER
font: Font.font("Arial Black", FontWeight.BOLD, 84)
x: 40
y: 20
},
// The bar under the text
Rectangle {
x: 25
y: 92
height: 58
width: image.width - 10
arcHeight: 10
arcWidth: 10
}
]
}
// Display the image with the clipping node
def cliptext = ImageView {
image: image
x: 20
y: 20
clip: gp
}
// Background rectangle
def background = Rectangle {
x: 20
y: 20
height: 140
width: image.width
arcHeight: 14
arcWidth: 14
fill: Color.BLACK
stroke:Color.MISTYROSE
strokeWidth: 4
opacity: 0.7
}
Stage {
title: "Clipping"
width: image.width + 40
height: image.height + 50
scene: Scene {
content: [
background,
cliptext
]
}
}
Tips
- To use more than one node to clip another node, create a
Groupnode, as shown in this example. - If the clipping node is positioned so that it does not overlap the node to be clipped, neither node will be displayed.
- You do not need to specify a fill color for the clipping node, because that node will become transparent and display the clipped node underneath.
- To produce an animation effect, bind a position or size of the clipping area to the
KeyFramevariable in aTimelineobject.
Differences Between Clipping and Shape Intersection and Subtraction
The ShapeIntersect and ShapeSubtract classes can be applied only to shapes and text with a fill area. The two classes are in the Desktop profile of the API, which means that they cannot be used for mobile deployment. The clip variable of the Node class can be applied to any node, and the Node class is in the Common profile of the API. This flexibility enables the clip variable to be used on mobile devices. Note, however, that currently several open issues in JIRA apply to the use of clipping on mobile devices.
The clip variable of the Node class has the following similarities to shape intersection and shape subtraction, which can cause some confusion.
Both the ShapeIntersect class and the clip variable of the Node class display only the area that is common to both objects. However, the ShapeIntersect operation ignores the fill color of individual shapes and applies a default fill color to the resulting shape. The transparency of the upper layer cannot be created with the ShapeIntersect class.
The clip variable can also produce an effect that looks like shape subtraction, in that the clipping path enables an underlying object to become visible. However, the resulting path is different. The ShapeSubtract operation removes pixels from the layer it is subtracted from. In contrast, the clipping operation changes the path of the underlying layer to match that of the clipping node, as demonstrated in the following example.
Example Code 3: Shape Subtraction That Mimics Clipping
The following example shows the use of the ShapeSubtract class to create text cut out from a rectangle, revealing an image placed underneath. The visual effect somewhat resembles the clipping effect produced by the clip variable of the Node class, in that an underlying layer is allowed to show through. However, in the ShapeSubtract operation, the shape of the image is not altered by the text or the interior rectangle.
In this example, the image is clipped with a rounded black rectangle of the same size to round its corners. The text and a smaller rounded rectangle are subtracted from the larger black rectangle, leaving cutout shapes, which then overlay an image. Because the ShapeSubtract class works only with shapes, the image itself cannot be included in the ShapeSubtract operation.

import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextOrigin;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.FontWeight;
import javafx.scene.shape.ShapeSubtract;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
// Import the image
def image = Image {
url: "{__DIR__}Vacation.jpg"
}
//Rounded rectangle for rounding image corners and shape cutout
def roundedrectangle = Rectangle {
x: 10
y: 10
width: bind image.width
height: bind image.height
arcHeight: 20
arcWidth: 20
}
// Display the image with rounded corners
def roundedimage = ImageView {
image: image
x: 10
y: 10
clip: roundedrectangle
}
// Create the rounded rectangle with text subtracted
def cutoutbox = ShapeSubtract {
a: roundedrectangle
b: [ Text {
content: "vacation"
textOrigin: TextOrigin.TOP
textAlignment: TextAlignment.CENTER
font: Font.font("Arial Black", FontWeight.EXTRA_BOLD, 36)
x: 260
y: 12
},
// The bar under the text
Rectangle {
x: 15
y: 50
width: bind image.width - 10
height: bind image.height - 50
arcHeight: 10
arcWidth: 10
}
]
}
Stage {
title: "Cutouts with Shape Subtraction"
width: image.width + 20
height: image.height + 50
scene: Scene {
fill: Color.DARKGREY
content: [
roundedimage, cutoutbox
]
}
}
API Documentation
Related How-To Topics
Last Updated: January 2010
[Return to How-To's Home]
Do you have comments about this article? We welcome your participation in our community. Please keep your comments civil and on point. You may optionally provide your email address to be notified of repliesyour information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use.