読者です 読者をやめる 読者になる 読者になる

JavaFX 3 Canvas

JavaFX

Canvasクラス Canvas class

JavaFXCanvasクラスはProcessingやJavaScriptcanvasと同じ様に使う事ができます.

Canvas class of JavaFX can be used the same as Processing or canvas of JavaScript.

GraphicContext

まずCanvasクラスが持っているGraphicContextを取得します.

First, get GraphicContext of Canvas class.

GraphicsContext ctx = canvas.getGraphicsContext2D();

fill, stroke

図形の輪郭を描く時はGraphicContextクラスの"stroke"で始まるメソッドを使用します. また図形の塗り潰す時はGraphicContextクラスの"fill"で始まるメソッドを使用します.

To draw outline of shape, use GraphicContext class's methods starts with "stroke". To paint all over a shape, use GraphicContext class's methods starts with "fill".

ctx.strokeOval(p.getX() - 5, p.getY() - 5, 10, 10)

path

パスを描く時はまずGraphicContextクラスのbeginPathメソッドでパスを開始します. そしてmoveTo, lineTo, quadraticCurveTo, bezierCurveTo, arc, arcTo, appendSVGPath, rect, closePathなどのメソッドでパスを作ります. パスの内側を塗り潰す時はGraphicContextクラスのfillメソッド, パスの輪郭を描く時はstrokeメソッドを使用します.

To generate path, firstly use beginPath method of GraphicContext class. After that, construct path with moveTo, lineTo, quadraticCurveTo, bezierCurveTo, arc, arcTo, appendSVGPath, rect or closePath methods. Finally, if you want to paint all over the region inside the path, use fill method of GraphicContext class. If you want to draw a outline of the path, use stroke method.

ctx.beginPath();
ctx.moveTo(points.get(0).getX(), points.get(0).getY());
points.stream().skip(1).forEach(p -> ctx.lineTo(p.getX(), p.getY()));
ctx.stroke();

clear

キャンバスをクリアする時はGraphicContextクラスのclearRectメソッドを使用します.

To clear the canvas, use clearRect method of GraphicContext.

ctx.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());

サンプル Sample

クリックされた点を直線で繋ぐプログラムです.

The following program draws lines between clicked points.

f:id:Jumpaku:20160729145906p:plain

View.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.canvas.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="canvassample.ViewController">
   <children>
      <Canvas fx:id="canvas" height="200.0" onMouseClicked="#handleClick" width="320.0" />
   </children>
</AnchorPane>

Main.java

package canvassample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("View.fxml"));
        stage.setScene(new Scene(root));
        stage.show();
    }

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

ViewController.java

package canvassample;

import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Point2D;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;

public class ViewController implements Initializable {
    private final List<Point2D> points = new LinkedList<>();
    
    @FXML
    private Canvas canvas;
    
    @FXML
    synchronized private void handleClick(MouseEvent e) {
        points.add(new Point2D(e.getX(), e.getY()));
        GraphicsContext ctx = canvas.getGraphicsContext2D();
        ctx.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
        
        points.forEach(p -> ctx.strokeOval(p.getX() - 5, p.getY() - 5, 10, 10));
        
        ctx.beginPath();
        ctx.moveTo(points.get(0).getX(), points.get(0).getY());
        points.stream().skip(1).forEach(p -> ctx.lineTo(p.getX(), p.getY()));
        ctx.stroke();
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }    
    
}