当前位置: 首页 > 知识库问答 >
问题:

JavaFX线图性能

赫连越
2023-03-14

我一直在努力提高JavaFX中线形图的性能,但没有取得很大的成功。我还发现,这似乎是一些程序员在试图显示大数据时发现的一个常见问题(big在这里代表数据大小

好吧,我在stackoverflow中发现了两个帖子,其中有一个类似的问题,即具有65000个数据点的JavaFX LineChart和JavaFX LineChart-绘图数组的性能问题。主题具有65000个数据点的JavaFX LineChart的性能问题最终建议(Adam)使用Ramer-Douglas-Peucker算法!减少LineChart中的数据点数量以加快速度。

然而,在科学和工程数据中,我们通常需要查看绘图形状,然后放大以查看绘图特定部分的细节。因此,如果我们使用Ramer-Douglas-Peucker算法,每次用户放大/缩小时,我们都需要重新绘制折线图,我认为这将需要大量处理。

因此,我想知道是否有人有一些关于如何在JavaFX中加速折线图的技巧。下面是一个示例代码,其中包含了我到目前为止学到的内容。

    import java.util.ArrayList;
    import java.util.List;
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.chart.LineChart;
    import javafx.scene.chart.NumberAxis;
    import javafx.scene.chart.XYChart;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;

    public class TestingLineChart extends Application {

@Override
public void start(Stage primaryStage) {
    long startTime, endTime;
    startTime = System.nanoTime();

    StackPane root = new StackPane();

    NumberAxis xAxis = new NumberAxis();
    NumberAxis yAxis = new NumberAxis();

    LineChart<Number, Number> lineChartPlot = new LineChart<>(xAxis, yAxis);
    // set them false to make the plot faster
    lineChartPlot.setAnimated(false);
    lineChartPlot.setCreateSymbols(false);

    List<XYChart.Data<Double, Double>> data = new ArrayList<>();

    Scene scene = new Scene(root, 300, 250);



    endTime = System.nanoTime();
    System.out.println("Time (ms) for creation: " + (endTime - startTime)/1e6);


    startTime = System.nanoTime();
    for (int n = 0; n < 1e5; n++) {
        data.add(new XYChart.Data(n, Math.random()));
    }
    endTime = System.nanoTime();
    System.out.println("Time (ms) for adding data: " + (endTime - startTime)/1e6);

    startTime = System.nanoTime();
    XYChart.Series dataSeries = new XYChart.Series<>();

    dataSeries.setName("data"); // taking the data
    dataSeries.getData().addAll(data); // taking the data

    endTime = System.nanoTime();
    System.out.println("Time (ms) for adding data to series: " + (endTime - startTime)/1e6);

    startTime = System.nanoTime();
    lineChartPlot.getData().add(dataSeries);
    endTime = System.nanoTime();
    System.out.println("Time (ms) for adding data to LineChart: " + (endTime - startTime)/1e6);

    startTime = System.nanoTime();
    root.getChildren().add(lineChartPlot);
    endTime = System.nanoTime();
    System.out.println("Time (ms) for adding LineChart StackPane: " + (endTime - startTime)/1e6);

    startTime = System.nanoTime();
    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
    endTime = System.nanoTime();
    System.out.println("Time (ms) for showing: " + (endTime - startTime)/1e6);
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}
}

正如您所看到的,如果运行此代码,最大的成本是渲染,而我无法使用这些计时来捕获渲染。那么,在我看来,改进的重点应该放在那里,但我不知道怎么做。

谢谢你。

共有3个答案

陈淳
2023-03-14

提高具有许多数据点的图表性能的是去除数据点的“形状”。

通过css例如:

.chart-line-symbol {
    -fx-shape: "";
}

或者确保它根本不可见:

.chart-line-symbol {
   -fx-background-insets: 0,0;
   -fx-background-radius: 0px; 
   -fx-padding: 0px;
   -fx-shape: "";
   -fx-background-color: transparent;
}

另一种方法是从图表中删除一些数据点。例如,只使用每3个。数据点或计算多个数据点的平均值。

林礼骞
2023-03-14

希望此评论不是徒劳的或来得太迟:

一些性能限制是JavaFX实现固有的:即许多操作是在JVM中计算的,而不是推送到基于OpenGL的底层硬件,数据点是在场景图中绘制的过大的节点,而不是动态的数据缩减和画布的使用。。。举几个例子。不幸的是,我们发现,如果没有围绕原始JavaFXChartAPI的更大的变通方法(例如,finalAPI方法),许多问题(和bug)都无法解决。

因此,我们开发/重新设计了(针对我们的内部应用程序)、开源,并在GitHub发布了基于JavaFX的图表库,希望其他人觉得它有用或愿意做出贡献:

https://github.com/GSI-CS-CO/chart-fx

其主要关注点:以25 Hz更新速率对数据集进行性能优化的实时数据可视化,其中包含数字信号处理应用中常见的1万500万个数据点。GitHub提供性能图、示例和留档:

https://github.com/GSI-CS-CO/chart-fx/raw/master/docs/pics/chartfx-example1.png https://github.com/GSI-CS-CO/chart-fx/raw/master/docs/pics/chartfx-performance1a.png https://github.com/GSI-CS-CO/chart-fx/raw/master/docs/pics/chartfx-performance1.png

为什么需要一个新的JavaFX库,以及与w.r.t.其他基于Java和C/Qt的库的性能比较,已在IPAC'19上介绍:https://ipac2019.vrws.de/papers/thprb028.pdf

N、 这是我的第一篇帖子,因此没有在线图片

施权
2023-03-14

我还将JavaFX图表用于一个科学应用程序,其中包含数十个thounsands的数据点,并且能够实现实时更新和绘制图形的速度。你需要做两件主要的事情。

首先,我认为Ramer-Douglas-Peucker算法不必要地复杂。假设您使用的是一个很好的简单连续函数,那么很容易观察到我们只有有限的显示分辨率,并且我们不需要为域中的每个像素最多三个或四个数据点来传递尽可能多的信息。例如,一个像素内的第一个和最后一个数据点各一个,像素内的最大值和最小值各一个。

您可以尝试这种策略,但其基本思想只是一个很好的快速单通下采样,基本上应该是无损的。(或者更准确地说,它不应该在光栅化的基础上增加额外的代表性损失。)它还将点数限制在可管理的范围内,根据我的经验,它的速度足以在缩放时重新绘制或进行实时数据更新。但是,如果您具有HiDPI的显示缩放功能,或者出于任何原因正在缩放图形组件,则可能会导致问题。

第二部分同样重要:即使将css设置为不绘制数据点形状,将节点添加到场景中仍然需要很长时间,这令人费解。为了解决这个问题,在不希望绘制形状的情况下,将线图子类化,并将dataItemAdded方法重写为no op就足够了。还应尽可能重复使用已添加到序列中的数据点,而不是添加新的数据点,即首选<代码>序列。getData()。获取(i)。setXValue(…) 和<代码>系列。getData()。获取(i)。setYValue(…) 至系列。setData(…) 或<代码>系列。getData()。添加(…)

 类似资料:
  • 主要内容:JavaFX曲线,QuadCurveJavaFX曲线 要创建三次曲线,请使用适当的构造函数。 设置三次曲线的主要参数是,,controlX1(控件点1X),controlY1(控件点1Y),controlX2(控件点2X)和controlY2(控件点2Y),,。 ,,和参数是曲线的起点和终点。,,和是控件点。 控制点(控制X1,控制Y1)影响线起点(startX,startY)和中间点之间的线段。控制点(controlX2,cont

  • 主要内容:JavaFX线条,示例 - 1,示例 - 2为了在JavaFX场景上渲染图形,我们需要基本的形状和颜色。 类是所有JavaFX场景图形节点的基本基类。它提供了转换和应用效果到任何节点的能力。 类是类的子类。所有较旧的JavaFX 2.x Builder中使用,但在JavaFX 8中这个类已弃用。 JavaFX线条 当在JavaFX场景图形上绘制时,使用屏幕坐标空间(系统)渲染线。 屏幕坐标系将()放在左上角。坐标沿着轴移动点。从上到下移动点

  • 我有一个使用折线图的JavaFX应用程序。我可以在应用程序中编写图表并清除它,但是当我想编写一个新系列并显示它时,我收到一个错误, 我懂意思,但不懂怎么修(我对Java很陌生,对FX就更不用说了)。 下面是我的控制器的相关代码(减去一些类声明): (由图表选项卡窗口中的“提交”按钮调用的方法) (上面方法调用的任务:) 图表第一次绘制,清除,然后异常发生。请求的堆栈跟踪如下: java.lang.

  • 本文向大家介绍具有多个系列(线)的JavaFX折线图示例,包括了具有多个系列(线)的JavaFX折线图示例的使用技巧和注意事项,需要的朋友参考一下 内联图,数据值表示由一条线连接的一系列点。在JavaFX中,可以通过实例化javafx.scene.chart.LineChart类来创建折线图。 在实例化此类时,必须传递Axis类的两个对象,它们代表x轴和y轴(作为构造函数的参数)。由于Axis类是

  • 我在JavaFx应用程序中面临一个问题。 前言:我不想具体到我的应用程序,而是想概括,这样像我这样的人就会对类似的情况有所了解。 背景:使用fxml文件和多线程概念实现一个Javafx应用程序。 总结:我试着做了一个应用程序,它基本上使用多线程来做一些任务,一旦多线程完成,它就会依次移动到另一个任务。在执行多线程操作时,主GUI会冻结。 我的所作所为, 现在,结果是这样的。如果我只是从控制器启动线

  • 我希望有条件地更改折线图的背景色。在给定的示例中,我希望修改图表,使任何具有Y值的部分 LineChartJavaFXTest。JAVA LineChart.css