1  import javafx.application.Application;
  2  import javafx.geometry.Point2D;
  3  import javafx.geometry.Pos;
  4  import javafx.scene.Scene;
  5  import javafx.scene.control.Label;
  6  import javafx.scene.control.TextField;
  7  import javafx.scene.layout.BorderPane;
  8  import javafx.scene.layout.HBox;
  9  import javafx.scene.layout.Pane;
 10  import javafx.scene.paint.Color;
 11  import javafx.scene.shape.Polygon;
 12  import javafx.stage.Stage;
 13  
 14  public class SierpinskiTriangle extends Application {
 15    @Override // Override the start method in the Application class
 16    public void start(Stage primaryStage) {       
 17      SierpinskiTrianglePane pane = new SierpinskiTrianglePane(); 
 18      TextField tfOrder = new TextField(); 
 19      tfOrder.setOnAction(
 20        e -> pane.setOrder(Integer.parseInt(tfOrder.getText())));
 21      tfOrder.setPrefColumnCount(4);
 22      tfOrder.setAlignment(Pos.BOTTOM_RIGHT);
 23  
 24      // Pane to hold label, text field, and a button
 25      HBox hBox = new HBox(10);
 26      hBox.getChildren().addAll(new Label("Enter an order: "), tfOrder);
 27      hBox.setAlignment(Pos.CENTER);
 28      
 29      BorderPane borderPane = new BorderPane();
 30      borderPane.setCenter(pane);
 31      borderPane.setBottom(hBox);
 32          
 33      // Create a scene and place it in the stage
 34      Scene scene = new Scene(borderPane, 200, 210);
 35      primaryStage.setTitle("SierpinskiTriangle"); // Set the stage title
 36      primaryStage.setScene(scene); // Place the scene in the stage
 37      primaryStage.show(); // Display the stage
 38      
 39      pane.widthProperty().addListener(ov -> pane.paint());
 40      pane.heightProperty().addListener(ov -> pane.paint());
 41    }
 42  
 43    /** Pane for displaying triangles */
 44    static class SierpinskiTrianglePane extends Pane {
 45      private int order = 0;
 46  
 47      /** Set a new order */
 48      public void setOrder(int order) {
 49        this.order = order;
 50        paint();
 51      }
 52  
 53      SierpinskiTrianglePane() {
 54      }
 55  
 56      protected void paint() {
 57        // Select three points in proportion to the panel size
 58        Point2D p1 = new Point2D(getWidth() / 2, 10);
 59        Point2D p2 = new Point2D(10, getHeight() - 10);
 60        Point2D p3 = new Point2D(getWidth() - 10, getHeight() - 10);
 61  
 62        this.getChildren().clear(); // Clear the pane before redisplay
 63  
 64        displayTriangles(order, p1, p2, p3);
 65      }
 66  
 67      private void displayTriangles(int order, Point2D p1, 
 68          Point2D p2, Point2D p3) {
 69        if (order == 0) {
 70          // Draw a triangle to connect three points
 71          Polygon triangle = new Polygon();
 72          triangle.getPoints().addAll(p1.getX(), p1.getY(), p2.getX(), 
 73            p2.getY(), p3.getX(), p3.getY());
 74          triangle.setStroke(Color.BLACK);
 75          triangle.setFill(Color.WHITE);
 76  
 77          this.getChildren().add(triangle);
 78        } 
 79        else {
 80          // Get the midpoint on each edge in the triangle
 81          Point2D p12 = p1.midpoint(p2);
 82          Point2D p23 = p2.midpoint(p3);
 83          Point2D p31 = p3.midpoint(p1);
 84  
 85          // Recursively display three triangles
 86          displayTriangles(order - 1, p1, p12, p31);
 87          displayTriangles(order - 1, p12, p2, p23);
 88          displayTriangles(order - 1, p31, p23, p3);
 89        }
 90      }
 91    }
 92    
 93    /**
 94     * The main method is only needed for the IDE with limited
 95     * JavaFX support. Not needed for running from the command line.
 96     */
 97    public static void main(String[] args) {
 98      launch(args);
 99    }
100  }