【问题标题】:Rendering JavaFX 2 charts in background在后台渲染 JavaFX 2 图表
【发布时间】:2012-10-25 07:35:56
【问题描述】:

我有一个用于数据分析的应用程序。该应用程序的很大一部分是能够根据组装的数据显示图表,并能够在一次批处理操作中导出大量任务。到目前为止,我一直在使用 JFreeChart,但我想使用本机 JavaFX 图表,以便导出的图表看起来仍然与它们在应用程序屏幕上的外观相同。

我使用的是 JavaFX 2.2.1 (jdk 7u6)。

我能够在一批中生成图表,但这意味着我必须冻结用户界面 (UI),因为这些图表必须在 JavaFX 应用程序线程上呈现。我使用 Platform.runLater(new Runnable() { ... });用于此的命令,包裹在生成图表的代码周围。

如果我将每个单独的图表生成包装到 Platform.runLater(new Runnable() { ... }); GUI 没有像以前那样冻结,但我也不会收到任何反馈,因为我无法检测到每个单独的图表何时生成(它们在稍后阶段运行,我无法控制何时可能发生,据我所知也没有可用的回调)。

对于这个特定的事件,我想向用户显示一个进度条,并且我希望这个进度条随着实际的图表生成而更新。

关于如何实现这一点的任何建议或提示?

【问题讨论】:

    标签: charts javafx-2


    【解决方案1】:

    这个问题在 Oracle JavaFX 论坛帖子中得到了解决:Render charts in background

    解决方案是有一个包含三个子任务的 SaveChartsTask:

    1. 在屏幕外场景图中创建图表。
    2. 将每个屏幕外图表的快照制作成 JavaFX 图像。
    3. 使用imageio 例程将JavaFX 图像导出到文件。

    任务的 workDone 属性允许监视操作的过程。通过将全部工作拆分为子任务,尽可能将工作从 JavaFX 应用程序线程中分离出来,并根据需要使用 CountDownLatches 和 BlockingQueues 来同步操作,UI 能够保持响应。

    【讨论】:

    • 您提供的链接与后台渲染图表无关!!你能更新一下吗?
    • Thx Mostafa,我还修复了答案中的链接。
    • :3 添加了最小长度要求!
    【解决方案2】:

    因为您似乎是 JavaFX-2 的新手。我建议您阅读 oracle 文档中的 JavaFX-2 Concurrency 文章。

    您的问题很容易通过使用Task 对象单独加载图表来解决(例如,每个图表一个任务)。引用教程页面:

    任务用于实现需要在后台线程上完成的工作逻辑。

    由于 Task 实现了 Work 接口,您可以使用您的 Task 来探测它们的 Worker.State。引用手册:

    可重用的 Worker 将从 CANCELLED、SUCCEEDED 或 FAILED 转换回 READY。

    这将解决您关于反馈的问题,因为您将始终能够知道任务是否仍在运行,因为 Worker.State 对象具有以下可能的状态:

    • 已取消
    • 失败
    • 准备好了
    • 正在运行
    • 预定
    • 成功

    至于你的进度条,你可以使用updateProgress(double done, double max)来设置你的任务进度,然后简单地通过将ProgressBar.progressProperty()绑定到Task.progressProperty()来设置你的进度条的进度。

    编辑

    回答您的评论:

    问题是在这种情况下,在生成 JavaFX 图表时,任务内部执行的工作,而代码需要在 JavaFX 应用程序线程内部执行

    来自教程:

    改为使用 javafx.concurrent 包提供的 JavaFX API,它负责与 UI 交互的多线程代码,并确保此交互发生在正确的线程上。

    这意味着在 Task 对象中执行的代码已经在 J​​avaFX 线程中执行。

    我希望它有所帮助。干杯

    【讨论】:

    • 实际上,这没有帮助。问题在于,在这种情况下,在生成 JavaFX 图表时在任务内部执行的工作,并且代码需要在 JavaFX 应用程序线程内执行,而不是在执行任务的线程中执行。所以我需要一些方法将图表渲染委托回 JavaFX 应用程序图表,同时仍然能够控制它何时执行(Platform.runLater 不提供)。
    • 来自教程页面:`使用 javafx.concurrent 包提供的 JavaFX API,它负责与 UI 交互的多线程代码,并确保这种交互发生在正确的线程上。`表示 Task 对象内执行的代码已经在 J​​avaFX 应用程序线程中
    • 没有。任务中发生的任何事情都发生在主 JavaFX 线程之外,这正是首先使用任务和服务的关键(执行需要在 GUI 线程之外发生的逻辑才能不锁定 GUI)。我面临的问题是我想在该任务中执行的代码依赖于使用该 JavaFX 应用程序线程。
    【解决方案3】:

    要在 JFX 线程上运行 JavaFX Task,您可以安排使用 Platform.runLater(myJFXTask); 运行任务。

    【讨论】:

      猜你喜欢
      • 2011-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-11
      • 2017-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多