JavaFX:在单独的非控制器类中更新UI

编程入门 行业动态 更新时间:2024-10-26 20:31:22
本文介绍了JavaFX:在单独的非控制器类中更新UI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个JavaFX程序,它启动由单独的类执行的任务。我想将该任务的进度状态输出到UI中的 Label 元素。我不能让这个工作。这是我的代码:

I have a JavaFX program that launches a task performed by a separate class. I would like to output the status of that task's progress to a Label element in the UI. I cannot get this to work. Here is my code:

Main.java:

public class Main extends Application { public void start(Stage primaryStage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("ui.fxml")); primaryStage.setTitle("Data collector"); primaryStage.setScene(new Scene(root, 400, 400)); primaryStage.show(); } public static void main(String[] args) { launch(args); } }

Controller.java:

我要更新的标签是通过全局去除来创建的 @FXML public Label label = new Label(); 。通过 new Thread创建一个新线程(new Task< Void>(){...})。start(); 运行 collect_data 来自 TaskRun 的方法。 TaskRun 类如下所示:

The label I want to update is created by delcaring globally @FXML public Label label = new Label();. Creates a new thread via new Thread(new Task<Void>() { ... }).start(); to run the collect_data method from TaskRun. The TaskRun class is stated below:

TaskRun.java:

class TaskRun { private Controller ui; TaskRun() { FXMLLoader loader = new FXMLLoader(getClass().getResource("ui.fxml")); ui = loader.getController(); } void collect_data() { for (int i = 0; i < 100; i++) { // do stuff... send_progress_to_ui(((float) i / (float)) * 100); } } void send_progress_to_ui(float percent) { new Thread(new Task<Void>() { @Override protected Void call() throws Exception { Platform.runLater(() -> ui.label.setText(Float.toString(percent_complete) + "%")); return null; } }).start(); } }

我得到 NullPointerException 在 Platform.runLater(...)的行上。

很明显,这种方法不起作用。如何通过此非控制器类更新UI TaskRun ?

So obviously, this method is not going to work. How do I update the UI through this non-controller class TaskRun?

推荐答案

你的设计对你在这里尝试做的事情并没有多大帮助。而不是一个完全隐藏任务并创建一个线程来运行它的类(这是非常不灵活的:如果你想将任务提交给现有的 Executor ?),你的班级应该执行任务。然后你可以只更新任务的进度,这是一个可观察的属性:

Your design is not really very helpful for what you are trying to do here. Instead of a class that hides the task entirely and creates a thread to run it (which is really inflexible: what if you want to submit the task to an existing Executor?), your class should implement the task. Then you can just update the task's progress, which is an observable property:

class TaskRun extends Task<Void> { @Override protected Void call() { for (int i = 0; i < 100; i++) { // do stuff... updateProgress(i, 100); } return null ; } }

现在在控制器中你可以执行:

Now in your controller you can just do:

TaskRun task = new TaskRun(); task.progressProperty().addListener((obs, oldProgress, newProgress) -> label.setText(String.format("%.2f percent complete", newProgress.doubleValue()*100))); new Thread(task).start();

或者,使用绑定而不是监听器:

Alternatively, use a binding instead of the listener:

label.textProperty().bind(task.progressProperty().asString("%.2f percent complete"));

这消除了你所有可怕的耦合,因为现在 TaskRun 不需要知道控制器类的任何信息。

This gets rid of all the horrendous coupling you have, because now TaskRun doesn't need to know anything about the controller class.

更多推荐

JavaFX:在单独的非控制器类中更新UI

本文发布于:2023-11-17 04:25:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1608821.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:控制器   类中   JavaFX   UI

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!