2017-09-05 10 views
2

マンダラを作成するJavaFXアプリケーションを作成しようとしています(幾何学的パターンの四角形、三角形、円を使って対称図形を作成しています)。私の計画は、ユーザーが1つの円弧上に図形を描けるようにすることでした。この円弧をコピーして回転させて曼荼羅を作成します。円内のJavaFXコンテンツを複製して回転させます

シングルアーク: completed single arc

完了曼荼羅: completed mandala

私は完成曼荼羅を作成する方法についてこだわっています。私はレイヤーを考えていましたが、どのようにキャンバスの非円弧領域を透明に設定するのですか?これを行うより良い方法はありますか?

これまでのコードは以下のとおりです。

@Override 
public void start(Stage primaryStage) 
{ 
    final double WIDTH = 400;  //constant for canvas size 
    final double HEIGHT = 400; 

    StackPane root = new StackPane(); 
    Canvas canvas = new Canvas(WIDTH, HEIGHT); 
    root.getChildren().add(canvas); 
    Scene scene = new Scene(root, 400, 400); 
    primaryStage.setTitle("Mandala"); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 

    GraphicsContext graphicsContext = canvas.getGraphicsContext2D(); 

    canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, 
     new EventHandler<MouseEvent>(){ 

      @Override 
      public void handle(MouseEvent event) { 
       graphicsContext.beginPath(); 
       graphicsContext.moveTo(event.getX(), event.getY()); 
       graphicsContext.stroke(); 
      } 
     }); 

    canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, 
     new EventHandler<MouseEvent>(){ 

      @Override 
      public void handle(MouseEvent event) { 
       graphicsContext.lineTo(event.getX(), event.getY()); 
       graphicsContext.stroke(); 
      } 
     }); 

    canvas.addEventHandler(MouseEvent.MOUSE_RELEASED, 
     new EventHandler<MouseEvent>(){ 

      @Override 
      public void handle(MouseEvent event) { 

      } 
     }); 

    int numSegments = 12; 
    int numdegrees = 360/numSegments; 
    int startAngle = 0; 

     // centreX, centreY, radiuisX (length of lines), radiusY, startAngle (0 is due east), numdegrees 
    Arc arc1 = new Arc(0, 0, 250, 250, startAngle, numdegrees); 
    arc1.setType(ArcType.ROUND); 
    arc1.setStroke(Color.BLACK); 
    arc1.setFill(null); 
    arc1.setStrokeWidth(1); 
    root.getChildren().add(arc1); 

} 
} 
+0

キャンバス描画プリミティブと、[Arc](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/shape/Arc.html)のようなシーングラフ描画プリミティブとを混在させるのはなぜですか? [arcTo](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/canvas/GraphicsContext.html#arcTo-double-double-double-double-double- )? – jewelsea

+0

私はこのことにとても新しいので、私は弧を描いた方法を見つけました! – Tortoise

答えて

0

クリップパスを使用します。このようにして、クリップパスの外側のものはすべて無視されます。さらにtransformは、回転したオブジェクトを描画するのに役立ちます。

private static void piePiece(GraphicsContext context, double width, double height, double radius, double angle) { 
    double cx = width/2; 
    double cy = height/2; 
    context.moveTo(cx, cy); 
    context.lineTo(cx + radius, cy); 
    context.arc(cx, cy, radius, radius, 0, angle); 
    context.closePath(); 
} 

@Override 
public void start(Stage primaryStage) { 
    Canvas canvas = new Canvas(600, 600); 
    GraphicsContext gc = canvas.getGraphicsContext2D(); 

    // rotation matrix rotating by 30° around (300, 300) 
    Affine rotate = new Affine(new Rotate(30, 300, 300)); 

    // draw first pie 
    gc.beginPath(); 
    piePiece(gc, 600, 600, 250, 30); 
    gc.stroke(); 

    gc.save(); 

    // create clip 
    gc.beginPath(); 
    piePiece(gc, 600, 600, 250, 30); 
    gc.clip(); 

    List<List<Point2D>> points = new ArrayList<>(); 

    Button btn = new Button("Complete"); 
    btn.setOnAction((ActionEvent event) -> { 
     // draw data stored in points variable 

     // remove old clip 
     gc.restore(); 
     for (int i = 30; i < 360; i += 30) { 
      // rotate by 30° 
      gc.transform(rotate); 

      gc.save(); 
      // draw piece 
      gc.beginPath(); 
      piePiece(gc, 600, 600, 250, 30); 
      gc.stroke(); 

      // create clip 
      gc.beginPath(); 
      piePiece(gc, 600, 600, 250, 30); 
      gc.clip(); 

      // draw lines 
      for (List<Point2D> lines : points) { 
       if (lines.size() >= 2) { 
        Iterator<Point2D> iter = lines.iterator(); 
        gc.beginPath(); 
        Point2D p = iter.next(); 
        gc.moveTo(p.getX(), p.getY()); 
        while (iter.hasNext()) { 
         p = iter.next(); 
         gc.lineTo(p.getX(), p.getY()); 
        } 
        gc.stroke(); 
       } 

      } 
      // remove clip 
      gc.restore(); 
     } 
    }); 

    class PressedHandler implements EventHandler<MouseEvent> { 

     List<Point2D> line; 

     @Override 
     public void handle(MouseEvent event) { 
      if (line == null) { 
       // add new line to lines list 
       line = new ArrayList<>(); 
       line.add(new Point2D(event.getX(), event.getY())); 
       points.add(line); 
       gc.beginPath(); 
       gc.moveTo(event.getX(), event.getY()); 
      } 
     } 

    } 

    PressedHandler handler = new PressedHandler(); 

    canvas.setOnMousePressed(handler); 
    canvas.setOnMouseDragged(event -> { 
     if (handler.line != null) { 
      // append point to line 
      handler.line.add(new Point2D(event.getX(), event.getY())); 
      gc.lineTo(event.getX(), event.getY()); 
     } 
    }); 
    canvas.setOnMouseReleased(event -> { 
     // complete line 
     handler.line = null; 
     gc.stroke(); 
    }); 

    VBox root = new VBox(btn, canvas); 

    Scene scene = new Scene(root); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 

簡潔にするために、線は描画中には表示されません。

+0

ありがとう!私はPoint2Dが抽象クラス、つまりhandler.line.add(新しいPoint2D.Double(event.getX()、event.getY()))のように2行を変更しなければなりませんでした。 – Tortoise

+0

間違ったクラスのTortiseをインポートしていますが、['javafx.geometry.Point2D'](https://docs.oracle.com/javase/8/javafx/api/javafx/geometry/Point2D.html)を使用する必要があります。 ['java.awt.geom.Point2D'](https://docs.oracle.com/javase/8/docs/api/java/awt/geom/Point2D.html)ではありません。一般に、AWTやSwingクラスをJavaFXプロジェクトにインポートすることは決してありません。あなたがツールキットを混在させる必要があるのでなければ(非常に珍しいでしょう)。 – jewelsea

関連する問題