javafx canvas stops displaying after a few seconds (I'm trying million ovals)

前端 未结 1 517
无人共我
无人共我 2021-01-28 13:38

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

相关标签:
1条回答
  • 2021-01-28 14:25

    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);
        }
    }
    
    0 讨论(0)
提交回复
热议问题