【发布时间】:2017-05-26 21:17:35
【问题描述】:
我有一个 JavaFX 程序,它启动一个由单独的类执行的任务。我想将该任务的进度状态输出到 UI 中的 Label 元素。我不能让它工作。这是我的代码:
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(); 创建一个新线程以从TaskRun 运行collect_data 方法。 TaskRun 类如下所述:
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(...) 在线。
很明显,这种方法是行不通的。如何通过这个非控制器类TaskRun更新UI?
【问题讨论】:
-
如果是控制器启动了Taskrun的实例,你可以这样做:new TaskRun(this),在TaskRun的构造函数中:TaskRun(Controller control){ ui = contro; ) 也许可以这样尝试;),但这取决于创建 Taskrun 的位置
-
它是在 Controller 的一个线程中创建的。也许这就是问题所在?
-
不确定,但我肯定不会像你那样工作,因为你会添加 2 个控制器实例,它必须相同,试试我写的并告诉我们
-
您能否至少告诉我们什么是 null 以及为什么您希望它不为 null?不过,一般来说,对链接到您从未实际显示的 UI 的控制器执行某些操作不会取得任何成果,即使您摆脱了所有异常。
-
单独创建
FXMLLoader不会导致加载 fxml 并因此创建控制器。这意味着ui是null。
标签: java multithreading user-interface javafx nullpointerexception