Java中的lineTo()非常缓慢

3

你好,我想使用Java绘制具有60fps刷新率的线条:

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;

import javafx.animation.Timeline;
import javafx.animation.KeyFrame;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.util.Duration;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;
import javafx.event.EventType;
import javafx.scene.paint.Color;

public class Example extends Application 
{
    public static void main(String[] args) 
    {
        launch(args);
    }

    @Override
    public void start(Stage theStage) 
    { 
        Group root = new Group();
        Scene theScene = new Scene( root );
        theStage.setScene( theScene );

        Canvas canvas = new Canvas( 512, 512 );
        root.getChildren().add( canvas );

        GraphicsContext gc = canvas.getGraphicsContext2D();           

        Timeline gameLoop = new Timeline();
        gameLoop.setCycleCount( Timeline.INDEFINITE );

        final long timeStart = System.nanoTime() -10000000000000l;

        KeyFrame kf = new KeyFrame(
            Duration.seconds(0.017),                // 60 FPS
            new EventHandler<ActionEvent>()
            {
                public void handle(ActionEvent ae)
                {                                        

                    // Clear the canvas
                    gc.clearRect(0, 0, (int)canvas.getWidth(),(int)canvas.getHeight());


                   for(int i=0;i<(int)(canvas.getWidth()/10);i++) {

                       //gc.setS
                       for(int j=0;j<10;j++)
                       {
                           if(j==0){gc.setStroke(Color.web("#000000"));}
                           else{gc.setStroke(Color.web("#aaaaaa"));}
                          gc.moveTo(j+i*10, 110);
                          gc.lineTo(j+i*10, canvas.getHeight());

                          //using gc.stroke instead of moveTo and lineTo works with good performance,but i need 1px width
                          //gc.strokeLine(j+i*10, 110, j+i*10, canvas.getHeight());
                       }

                   }
                   gc.stroke();              

                }
            });

        gameLoop.getKeyFrames().add( kf );
        gameLoop.play();

        theStage.show();

        theScene.widthProperty().addListener(observeable -> {
                    canvas.setWidth(theScene.getWidth());
                    });       

    }
}

然而这种方法非常缓慢,而且程序会崩溃。使用 "strokeLine()" 可以正常运行,但我真的需要画1像素宽度的线。

我想我必须在绘制完整个场景之前将绘图保存在缓冲区中。但我读到 javafx 正在为你处理底层的东西,所以是否有另一种方法可以绘制1像素的线条呢?


1
你能给我们更多信息吗?每帧的线条是否会改变?线条数组包含什么?你有一个最小的代码示例吗? - Derlin
是的,每帧的线条都在变化。但这个例子中不是这样的。问题只是使用lineTo()而不是strokeLine()时的性能问题。 - user3776738
1
你说用strokeLine()可以正常工作,但是你“真的需要画1像素宽的线”。那么,strokeLine如何防止你绘制1像素宽的线呢? - jewelsea
1个回答

3

您没有在每次迭代中将路径重置为空。因此,路径笔画正在累积:第一次迭代有500条线,第二次迭代有1000条,第三次迭代有1500条等等。

您需要

gc.beginPath();

在调用gc.clearRect(...);之后。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接