如何在Javafx的画布上提升线条绘制速度

4

我正在使用Javafx制作一个基本的绘图应用程序。我想知道是否有一些方法可以增加画布上线条的绘制速度。

public class MouseListener implements EventHandler<MouseEvent>{

    @Override
    public void handle(MouseEvent event) {


        if(event.getSource() == canvas){
            canvas.getParent().setCursor(Cursor.CROSSHAIR);

        }


        if(event.getEventType() == MouseEvent.MOUSE_PRESSED){

            x1 = event.getX(); 
            y1 = event.getY(); 

        }else if(event.getEventType() == MouseEvent.MOUSE_MOVED){


            pGraphics.reset();

            x2 = event.getX();
            y2 = event.getY();

            mouseClick = 0; 

            pGraphics.drawLine(x1, y1, x2, y2);

        }


    }


public void drawLine(double x1, double y1, double x2, double y2){

    gc.strokeLine(x1, y1, x2, y2);

}

public void reset()
{
    gc.clearRect(0,0, gc.getCanvas().getWidth(), gc.getCanvas().getHeight());
}

正如您所看到的,这个绘图过程非常简单,使用MouseListener来检测线条开始的位置(x1, y1),并且同样适用于设置线条结束的位置(x2, y2)。正如您所看到的,我在绘制后清除了线条,这是我的意图,因为这个函数应该“展示”线条应该走的方向,例如像Microsoft Paint中使用的线条功能。然而,所有这些问题都在于,线条“滞后”于光标,当光标以正确的速度移动时,情况会更加明显。所以问题是:这是否与我的绘制函数、画布绘制函数、MouseListener的刷新率或其他完全不同的东西有关,还是全部都有关系?非常感谢对此提出建议。

3个回答

3

我认为你的方法完全错误。更加简单和有效的方法是在画布上放置一个线节点,只需修改该行的几何数据,而不是不断清除画布并重新绘制线条。(你还应该问自己是否在这里使用画布是正确的事情,但这是仅有你能决定的,因为你没有提供任何你想要用画布做什么的信息。)


1
我需要制作一个绘画应用程序。因此,画布是我的绘图板,所有线条、形状等都在上面绘制。我已经建立了一个图层系统,对于每个图层,我添加一个画布并将该画布的GraphicsContext设置为当前画布。我考虑过只是将它们添加到一个面板中,而不是使用画布。您认为这样做会更好吗? - Skarsh
1
这非常取决于您的程序性质。如果它的性质更像是矢量绘图程序,并且您需要在绘制后编辑几何图形,则使用面板可能是更好的选择。 - mipa

2
问题可能不在于绘图速度,而是输入反应延迟,类似于问题correct way to move a node by dragging in javafx 2?中所讨论的那样。
尝试一些链接问题答案中的方法,看看是否有所帮助。
请注意,如果是这种情况,则使用画布或场景图并不会对性能问题产生影响,因为问题与输入事件处理相关,而不是渲染系统。
相关的 bug 跟踪票据:Performance issue when tracking mouse events

我看到您提供了一个解决方案,设置了未记录的 JVM 标志

-Djavafx.animation.fullspeed=true

我该如何开始做呢?

那不是我写的解决方案,请小心未记录的标志可能会在将来的 Java 版本中被删除或其行为被修改(尽管在这种情况下我认为这是不太可能的)。然而,值得一试。
要了解如何设置命令行标志,请参见:Java -D 命令行参数的正确用法和名为“-Dproperty=value”的 Java man 文档 部分。
只需输入以下命令即可: java -Djavafx.animation.fullspeed=true my package.MyMainClassjava -Djavafx.animation.fullspeed=true myjar.jar(当然,将 My 值替换为适用于您的应用程序的相应值)。

谢谢!我一定会去看看的! - Skarsh
我看到您提供了一种解决方案,设置了未记录的JVM标志-Djavafx.animation.fullspeed=true。我该如何开始做这件事呢? - Skarsh

0
在您的简单示例中,在复位函数中用背景色绘制一条线覆盖先前的x1、y1、x2、y2线,然后再绘制新线会更有效率。
但是,如果移动了1像素,用户不太可能注意到差异。
如果用户只在坐标上玩 x1 = 50,y1 = 50到x2'=51,y2'=50或x2''=50,y2=51 您仍将清除整个画布,这对于仅更改了1-2个像素的画布来说相当愚蠢,而画布可以具有数千或数百万个像素。
但无论如何,为了优化一些速度,您可以跳过一些重绘而对用户几乎没有影响。因此,添加if以检查前一个x2和y2之间的差异与当前x2和y2相比是否大于x个像素即可。

没错,我没有考虑到这一点。谢谢!我一定会尝试这个方法的。 - Skarsh

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