首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaFX LineChart性能

JavaFX LineChart性能
EN

Stack Overflow用户
提问于 2016-01-13 16:14:31
回答 4查看 5.8K关注 0票数 14

我一直在努力提高LineChart在JavaFX中的性能,但没有取得很大的成功。我还发现,这似乎是一些程序员在试图显示大数据时发现的一个常见问题(这里的大表示数据> 10,000)。例如,这类数据在科学和工程中非常常见,如果我们能够找到如何加快LineChart in JavaFX的速度,那就太好了。

嗯,我在堆栈溢出中找到了两个类似的问题具有65000个数据点的JavaFX LineChart的性能问题JavaFX LineChart -绘制数组的帖子。主题具有65000个数据点的JavaFX LineChart的性能问题最后提出了使用Ramer-Douglas-Peucker算法的建议(由Adam提出)!以减少进入LineChart的数据点的数量以加快速度。

然而,在科学和工程数据中,我们通常需要看到图的形状,然后放大以查看图的特定部分的细节。因此,如果我们使用拉姆尔-道格拉斯-派克算法,我们将需要重新绘制的LineChart每次用户放大/缩小,我认为,将花费大量的处理。

因此,我想知道是否有人在如何加快LineChart in JavaFX方面有一些建议。下面是一个示例代码,其中包含了我到目前为止学到的内容。

代码语言:javascript
复制
    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);
}
}

正如您所看到的,如果您运行这段代码,最大的成本是在呈现方面,而我无法使用这些时间捕获它。然后,在我看来,改进应该集中在那里,但我不知道如何改进。

谢谢。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-03-29 13:15:33

我还使用JavaFX图表进行科学应用,有几十个数据点,并且能够实现实时更新和绘制图形的速度。你需要做两件主要的事情。

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

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

第二部分同样重要:即使您将css设置为不绘制数据点形状,将节点添加到场景仍然要花费相当长的时间。要解决这个问题,只需子类LineChart并覆盖dataItemAdded方法就足够了,在不想绘制形状的情况下,它是不操作的。您还应该在可能的情况下重用已经添加到系列中的数据点,而不是添加新的数据点,比如更喜欢series.getData().get(i).setXValue(...)series.getData().get(i).setYValue(...)而不是series.setData(...)series.getData().add(...)

票数 13
EN

Stack Overflow用户

发布于 2019-06-12 18:04:39

希望这句话不会白费,也不会来得太晚:

一些性能限制是JavaFX实现所固有的:即。许多操作是在JVM中计算的,而不是被推送到底层的基于OpenGL的HW,数据点是在场景图中绘制的过大的Nodes,而不是动态的数据缩减和Canvas的使用.举几个例子。不幸的是,我们发现,如果没有更大的解决方法(例如,final API方法),这些问题(和bug)就无法在原始JavaFX Chart API中得到解决。

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

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

它的主要关注点:性能优化的实时数据可视化在25赫兹的数据集更新率与数万至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库,以及性能比较。其他基于Java和C++/Qt的库也出现在IPAC'19:https://ipac2019.vrws.de/papers/thprb028.pdf上。

注:这是我的第一篇文章,因此没有在线图片。

票数 7
EN

Stack Overflow用户

发布于 2017-10-20 08:20:38

提高多个数据点的图表性能的是删除数据点的“形状”。

例如,通过css:

代码语言:javascript
复制
.chart-line-symbol {
    -fx-shape: "";
}

或者确保它根本看不见:

代码语言:javascript
复制
.chart-line-symbol {
   -fx-background-insets: 0,0;
   -fx-background-radius: 0px; 
   -fx-padding: 0px;
   -fx-shape: "";
   -fx-background-color: transparent;
}

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34771612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档