I have a lot of data to draw onto a canvas. Thefore I would like to do this on a background thread. In my example I create two canvas objects and while the first one is rendered I replace it with the other one.
Anyway, while the painting seems to be fast, when reattaching the canvas to the scene graph the UI seems to freeze and is getting slow.
Many thanks in advance.
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class DrawInBackground extends Application {
Canvas cv = new Canvas(1000, 1000);
GraphicsContext gc;
Canvas dummer = new Canvas(1000, 1000);
@Override
public void start(Stage stage) throws Exception {
gc = cv.getGraphicsContext2D();
VBox v = new VBox();
Button b = new Button("draw");
StackPane stackPane = new StackPane();
stackPane.getChildren().add(cv);
b.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
stackPane.getChildren().clear();
stackPane.getChildren().add(dummer);
CanvasPainter cvp = new CanvasPainter(gc);
cvp.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent event) {
stackPane.getChildren().clear();
stackPane.getChildren().add(cv);
System.out.println(System.currentTimeMillis() + " transfer done\n");
}
});
Thread t = new Thread(cvp);
t.setDaemon(true);
t.start();
}
});
v.getChildren().addAll(b, stackPane);
stage.setScene(new Scene(v));
stage.setTitle("Draw on background thread.");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
public class CanvasPainter extends Task<Canvas> {
GraphicsContext gc;
public CanvasPainter(GraphicsContext gc) {
this.gc = gc;
}
@Override
protected Canvas call() throws Exception {
System.out.println(System.currentTimeMillis() + " Painting");
gc.clearRect(0, 0, 1000, 1000);
gc.setStroke(Color.RED);
for (int i = 0; i < 2000000; i++) {
gc.strokeLine(Math.random() * 1000, Math.random() * 1000, Math.random() * 1000, Math.random() * 1000);
}
System.out.println(System.currentTimeMillis() + " done");
return null;
}
}
}