Shapes

Paul Ngugi - Jun 20 - - Dev Community

JavaFX provides many shape classes for drawing texts, lines, circles, rectangles, ellipses, arcs, polygons, and polylines. The Shape class is the abstract base class that defines the common properties for all shapes. Among them are the fill, stroke, and strokeWidth properties. The fill property specifies a color that fills the interior of a shape. The stroke property specifies a color that is used to draw the outline of a shape. The strokeWidth property specifies the width of the outline of a shape. This section introduces the classes Text, Line, Rectangle, Circle, Ellipse, Arc, Polygon, and Polyline for drawing texts and simple shapes. All these are subclasses of Shape, as shown in Figure below.

Image description

Text

The Text class defines a node that displays a string at a starting point (x, y), as shown in Figure below (a). A Text object is usually placed in a pane. The pane’s upper-left corner point is (0, 0) and the bottom-right point is (pane.getWidth(), pane.getHeight()). A string may be displayed in multiple lines separated by \n. The UML diagram for the Text class is
shown in Figure below. The program below gives an example that demonstrates text, as shown in Figure below (b).

Image description

Image description

package application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.FontPosture;

public class ShowText extends Application {
    @Override // Override the start method in the Application class
    public void start(Stage primaryStage) {
        // Create a pane to hold the texts
        Pane pane = new Pane();
        pane.setPadding(new Insets(5, 5, 5, 5));
        Text text1 = new Text(20, 20, "Programming is fun");
        text1.setFont(Font.font("Courier", FontWeight.BOLD, FontPosture.ITALIC, 15));
        pane.getChildren().add(text1);

        Text text2 = new Text(60, 60, "Programming is fun\nDisplay text");
        pane.getChildren().add(text2);

        Text text3 = new Text(10, 100, "Programming is fun\nDisplay text");
        text3.setFill(Color.RED);
        text3.setUnderline(true);
        text3.setStrikethrough(true);
        pane.getChildren().add(text3);

        // Create a scene and place it in the stage
        Scene scene = new Scene(pane);
        primaryStage.setTitle("ShowText"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

Enter fullscreen mode Exit fullscreen mode

The program creates a Text (line 19), sets its font (line 20), and places it to the pane (line 21). The program creates another Text with multiple lines (line 23) and places it to the pane (line 24). The program creates the third Text (line 26), sets its color (line 27), sets an underline and a strike through line (lines 28–29), and places it to the pane (line 30).

Line

A line connects two points with four parameters startX, startY, endX, and endY, as shown in Figure below (a). The Line class defines a line. The UML diagram for the Line class is shown in Figure below. The program below gives an example that demonstrates text, as shown in Figure below (b).

package application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.shape.Line;

public class ShowLine extends Application {
    @Override // Override the start method in the Application class
    public void start(Stage primaryStage) {
        // Create a scene and place it in the stage
        Scene scene = new Scene(new LinePane(), 200, 200);
        primaryStage.setTitle("ShowLine"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

class LinePane extends Pane{
    public LinePane() {
        Line line1 = new Line(10, 10, 10, 10);
        line1.endXProperty().bind(widthProperty().subtract(10));
        line1.endYProperty().bind(heightProperty().subtract(10));
        line1.setStrokeWidth(5);
        line1.setStroke(Color.GREEN);
        getChildren().add(line1);

        Line line2 = new Line(10, 10, 10, 10);
        line2.startXProperty().bind(widthProperty().subtract(10));
        line2.endYProperty().bind(heightProperty().subtract(10));
        line2.setStrokeWidth(5);
        line2.setStroke(Color.GREEN);
        getChildren().add(line2);
    }
}

Enter fullscreen mode Exit fullscreen mode

Image description

Image description

The program defines a custom pane class named LinePane (line 24). The custom pane class creates two lines and binds the starting and ending points of the line with the width and height of the pane (lines 27–28, 34–35) so that the two points of the lines are changed as the pane is resized.

Rectangle

A rectangle is defined by the parameters x, y, width, height, arcWidth, and arcHeight, as shown in Figure below (a). The rectangle’s upper-left corner point is at (x, y) and parameter aw (arcWidth) is the horizontal diameter of the arcs at the corner, and ah (arcHeight) is the vertical diameter of the arcs at the corner.

Image description

The Rectangle class defines a rectangle. The UML diagram for the Rectangle class is shown in Figure below. The program below gives an example that demonstrates rectangles, as shown in Figure above (b).

Image description

package application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.text.Text;
import javafx.scene.shape.Rectangle;

public class ShowRectangle extends Application {
    @Override // Override the start method in the Application class
    public void start(Stage primaryStage) {
        // Create a pane
        Pane pane = new Pane();

        // Create rectangles and add to pane
        Rectangle r1 = new Rectangle(25, 10, 60, 30);
        r1.setStroke(Color.BLACK);
        r1.setFill(Color.WHITE);
        pane.getChildren().add(new Text(10, 27, "r1"));
        pane.getChildren().add(r1);

        Rectangle r2 = new Rectangle(25, 50, 60, 30);
        pane.getChildren().add(new Text(10, 67, "r2"));
        pane.getChildren().add(r2);

        Rectangle r3 = new Rectangle(25, 90, 60, 30);
        r3.setArcWidth(15);
        r3.setArcHeight(25);
        pane.getChildren().add(new Text(10, 107, "r3"));
        pane.getChildren().add(r3);

        for(int i = 0; i < 4; i++) {
            Rectangle r = new Rectangle(100, 50, 100, 30);
            r.setRotate(i * 360 / 8);
            r.setStroke(Color.color(Math.random(), Math.random(), Math.random()));
            r.setFill(Color.WHITE);
            pane.getChildren().add(r);
        }

        // Create a scene and place it in the stage
        Scene scene = new Scene(pane, 250, 150);
        primaryStage.setTitle("ShowRectangle"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

Enter fullscreen mode Exit fullscreen mode

The program creates multiple rectangles. By default, the fill color is black. So a rectangle is filled with black color. The stroke color is white by default. Line 18 sets stroke color of rectangle r1 to black. The program creates rectangle r3 (line 27) and sets its arc width and arc height (lines 28–29). So r3 is displayed as a rounded rectangle.

The program repeatedly creates a rectangle (line 34), rotates it (line 35), sets a random stroke color (lines 36), its fill color to white (line 37), and adds the rectangle to the pane (line 38).

If line 37 is replaced by the following line

r.setFill(null);

the rectangle is not filled with a color. So they are displayed as shown in Figure above (c).

Circle and Ellipse

You have used circles in several examples early in the previous posts. A circle is defined by its parameters centerX, centerY, and radius. The Circle class defines a circle. The UML diagram for the Circle class is shown in Figure below.

Image description

An ellipse is defined by its parameters centerX, centerY, radiusX, and radiusY, as shown in Figure below (a). The Ellipse class defines an ellipse. The UML diagram for the Ellipse class is shown in Figure below. The program below gives an example that demonstrates ellipses, as shown in Figure below (b).

Image description

Image description

Image description

The program repeatedly creates an ellipse (line 17), sets a random stroke color (lines 18), sets its fill color to white (line 19), rotates it (line 20), and adds the rectangle to the pane (line 21).

Arc

An arc is conceived as part of an ellipse, defined by the parameters centerX, centerY, radiusX, radiusY, startAngle, length, and an arc type (ArcType.OPEN, ArcType.CHORD, or ArcType.ROUND). The parameter startAngle is the starting angle; and length is the spanning angle (i.e., the angle covered by the arc). Angles are measured in degrees and follow the usual mathematical conventions (i.e., 0 degrees is in the easterly direction, and positive angles indicate counterclockwise rotation from the easterly direction), as shown in Figure below (a).

Image description

The Arc class defines an arc. The UML diagram for the Arc class is shown in Figure below. The program below gives an example that demonstrates ellipses, as shown in Figure above (b).

Image description

package application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.scene.text.Text;

public class ShowArc extends Application {
    @Override // Override the start method in the Application class
    public void start(Stage primaryStage) {
        // Create a pane
        Pane pane = new Pane();

        Arc arc1 = new Arc(150, 100, 80, 80, 30, 35); // Create an arc
        arc1.setFill(Color.RED); // Set fill color
        arc1.setType(ArcType.ROUND); // Set arc type
        pane.getChildren().add(new Text(210, 40, "arc1: round"));
        pane.getChildren().add(arc1); // Add arc to pane

        Arc arc2 = new Arc(150, 100, 80, 80, 30 + 90, 35);
        arc2.setFill(Color.WHITE);
        arc2.setType(ArcType.OPEN);
        arc2.setStroke(Color.BLACK);
        pane.getChildren().add(new Text(20, 40, "arc2: open"));
        pane.getChildren().add(arc2);

        Arc arc3 = new Arc(150, 100, 80, 80, 30 + 180, 35);
        arc3.setFill(Color.WHITE);
        arc3.setType(ArcType.CHORD);
        arc3.setStroke(Color.BLACK);
        pane.getChildren().add(new Text(20, 170, "arc3: chord"));
        pane.getChildren().add(arc3);

        Arc arc4 = new Arc(150, 100, 80, 80, 30 + 270, 35);
        arc4.setFill(Color.GREEN);
        arc4.setType(ArcType.CHORD);
        arc4.setStroke(Color.BLACK);
        pane.getChildren().add(new Text(210, 170, "arc4: chord"));
        pane.getChildren().add(arc4);

        // Create a scene and place it in the stage
        Scene scene = new Scene(pane, 300, 200);
        primaryStage.setTitle("ShowArc"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

Enter fullscreen mode Exit fullscreen mode

The program creates an arc arc1 centered at (150, 100) with radiusX 80 and radiusY 80. The starting angle is 30 with length 35 (line 15). arc1’s arc type is set to ArcType.ROUND **(line 18). Since **arc1’s fill color is red, arc1 is displayed filled with red round.

The program creates an arc arc3 centered at (150, 100) with radiusX 80 and radiusY 80. The starting angle is 30+180 with length 35 (line 29). Arc3’s arc type is set to ArcType.CHORD (line 31). Since arc3’s fill color is white and stroke color is black, arc3 is displayed with black outline as a chord.

Angles may be negative. A negative starting angle sweeps clockwise from the easterly direction, as shown in Figure below. A negative spanning angle sweeps clockwise from the starting angle. The following two statements define the same arc:

new Arc(x, y, radiusX, radiusY, -30, -20);
new Arc(x, y, radiusX, radiusY, -50, 20);

The first statement uses negative starting angle -30 and negative spanning angle -20, as shown in Figure below (a). The second statement uses negative starting angle -50 and positive spanning angle 20, as shown in Figure below (b).

Image description

Note that the trigonometric methods in the Math class use the angles in radians, but the angles in the Arc class are in degrees.

Polygon and Polyline

The Polygon class defines a polygon that connects a sequence of points, as shown in Figure below (a). The Polyline class is similar to the Polygon class except that the Polyline class is not automatically closed, as shown in Figure below (b).

Image description

The UML diagram for the Polygon class is shown in Figure below.

Image description

The program below gives an example that creates a hexagon, as shown in Figure below.

Image description

package application;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.shape.Polygon;
//import javafx.scene.shape.Polyline;

public class ShowPolygon extends Application {
    @Override // Override the start method in the Application class
    public void start(Stage primaryStage) {
        // Create a pane, a polygon, and place polygon to pane
        Pane pane = new Pane();
        Polygon polygon= new Polygon();
        pane.getChildren().add(polygon);
        polygon.setFill(Color.WHITE);
        polygon.setStroke(Color.BLACK);
        ObservableList<Double> list = polygon.getPoints();

        final double WIDTH = 200, HEIGHT = 200;
        double centerX = WIDTH / 2, centerY = HEIGHT / 2;
        double radius = Math.min(WIDTH,  HEIGHT) * 0.4;

        // Add points to the polygon list
        for(int i = 0; i < 6; i++) {
            list.add(centerX + radius * Math.cos(2 * i * Math.PI / 6));
            list.add(centerY - radius * Math.sin(2 * i * Math.PI / 6));
        }

        // Create a scene and place it in the stage
        Scene scene = new Scene(pane, WIDTH, HEIGHT);
        primaryStage.setTitle("ShowPolygon"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

Enter fullscreen mode Exit fullscreen mode

The program creates a polygon (line 16) and adds it to a pane (line 17). The polygon.getPoints() method returns an ObservableList (line 20), which contains the add method for adding an element to the list (lines 28–29). Note that the value passed to add(value) must be a double value. If an int value is passed, the int value would be automatically boxed into an Integer. This would cause an error because the ObservableList consists of Double elements.

The loop adds six points to the polygon (lines 27–30). Each point is represented by its x- and y-coordinates. For each point, its x-coordinate is added to the polygon’s list (line 28) and then its y-coordinate is added to the list (line 29). The formula for computing the x- and
y-coordinates for a point in the hexagon is illustrated in Figure above (a).

If you replace Polygon by Polyline, the program displays a polyline as shown in Figure above (b). The Polyline class is used in the same way as Polygon except that the starting and ending point are not connected in Polyline.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .