I\'m trying to display a million ovals in a canvas dynamicly every second. I use a thread as the rendering thread, but my problem is, after a few secondes, the canvas freezes an
What is (probably) going wrong and how to fix it
Don't use a Task and a separate thread for the drawing. Modifications to the scene graph (including a canvas), must be done on the JavaFX application thread. Instead use a Timeline (which will implicitly execute it's keyframe code on the JavaFX application thread). If you must use a task, then at least use Platform.runLater to surround your calls into the JavaFX API that modify the active scene graph.
Potential scaling issue
A million ovals per second is probably a lot to try to draw in a single frame. You may wish to run some benchmark tests to see what a usable number is for your target platforms (though my sample below does seem to execute fine without a performance issue on a 2014 Macbook Pro).
Sample Code
Here is an updated sample with a Timeline that you could try. It seems to work fine for me (Java 8u60, OS X 10.9.5) - rendering 250,000 circles each second:
import javafx.animation.*;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.canvas.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class LotsaCircles extends Application {
private static final double SIZE = 500;
public void start(Stage stage) {
Canvas canvas = new Canvas(SIZE, SIZE);
Timeline timeline = new Timeline(
new KeyFrame(
Duration.seconds(0),
event -> drawShapes(canvas.getGraphicsContext2D())
),
new KeyFrame(Duration.seconds(1))
);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
stage.setScene(new Scene(new Group(canvas)));
stage.show();
}
private void drawShapes(GraphicsContext gc) {
gc.clearRect(0, 0, SIZE, SIZE);
gc.setFill(Color.GREEN);
gc.setStroke(Color.BLUE);
gc.setLineWidth(1);
double widthOval = 1;
double heightOval = 1;
for (int i = 0; i < SIZE; ++i) {
for (int j = 0; j < SIZE; ++j) {
if (Math.random() < 0.5) {
gc.fillOval(i * widthOval, j * heightOval, widthOval, heightOval);
}
else {
gc.strokeOval(i * widthOval, j * heightOval, widthOval, heightOval);
}
}
}
}
public static void main(String[] args) {
launch(args);
}
}