javafx - 更新 JavaFX 状态标签
问题描述
我有一个使用模型/视图/控制器的 JavaFX 程序,我想要一个长时间运行的模型来更新视图上的状态标签。我发现有人建议使用Timeline类来执行此操作。我实现了它,期望每一秒,状态标签都会更新。但是,仅显示最终状态。我究竟做错了什么?
我的控制器看起来像:
@FXML
private Button pullApplicantsButton;
@FXML
private Label statusLabel;
@FXML
private DatePicker orientationDate;
@FXML
private Spinner numberOfApplicants;
@FXML
private void pullApplicants() throws Exception {
SelectApplicantsModel selectApplicantsModel = new SelectApplicantsModel(orientationDate.getValue() , ( int ) numberOfApplicants.getValue() , this.statusLabel);
selectApplicantsModel.process();
}
我的模型看起来像:
public SelectApplicantsModel(LocalDate nextOrientationDate, int numberOfApplicants , Label statusLabel ) throws FileNotFoundException {
this.nextOrientationDate = nextOrientationDate;
this.numberOfApplicants = numberOfApplicants;
this.statusLabel = statusLabel;
}
public void process() throws Exception {
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds( 1 ) , event -> {
statusLabel.setText( programStatus );
})
);
timeline.setCycleCount( Animation.INDEFINITE );
timeline.play();
programStatus = "starting";
changeSearchStringToIncludeOrientationDate(nextOrientationDate);
MemberClicks memberClicks = new MemberClicks();
programStatus = "retrieving profiles";
JsonArray applicantProfilesJsonArray = memberClicks.getProfiles(searchJsonArray);
programStatus = "converting profiles";
并且视图看起来像:
<Label text="Picks the next 30 applicants for the upcoming orientation. Applicants whose Memberclick's OrientationDate matches the next orientation date get priority, followed by those with the oldest normalized application date." wrapText="true" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0" />
<Label text="Date of next orientation:" GridPane.columnIndex="0" GridPane.rowIndex="1" />
<DatePicker fx:id="orientationDate" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label text="Number of applicants to pull:" GridPane.columnIndex="0" GridPane.rowIndex="2" />
<Spinner fx:id="numberOfApplicants" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Button fx:id="pullApplicantsButton" mnemonicParsing="false" onAction="#pullApplicants" text="Pull Applicants" GridPane.columnIndex="0" GridPane.rowIndex="4" />
<Button fx:id="closeWindowButton" mnemonicParsing="false" onAction="#closeWindow" text="Close Window" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label fx:id="statusLabel" text="" wrapText="true" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="5" />
解决方案
您可以将 aTask
用于您的目的,它在后台线程中完成所有工作,这样 GUI 线程就不会被阻塞。这是一个最小的例子:
控制器类:
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class Controller {
@FXML
private Label statusLabel;
@FXML
public void handleStartBtnClick() {
MyTask myTask = new MyTask();
statusLabel.textProperty().bind(myTask.messageProperty());
new Thread(myTask).start();
}
}
我的任务类:
package sample;
import javafx.concurrent.Task;
public class MyTask extends Task<Void> {
@Override
protected Void call() throws Exception {
updateMessage("starting");
// while (...) {
// do something:
// changeSearchStringToIncludeOrientationDate(nextOrientationDate);
// MemberClicks memberClicks = new MemberClicks();
Thread.sleep(1000); // just for demonstration purpose
// Update the status:
updateMessage("retrieving profiles");
Thread.sleep(1000);
// Do next step:
// ...
updateMessage("converting profiles");
Thread.sleep(1000);
// } End of while loop
return null;
}
@Override
protected void succeeded() {
updateMessage("succeeded");
}
}
FXML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<Button onAction="#handleStartBtnClick" text="Start background task"/>
<Label fx:id="statusLabel" text="Status"/>
</children>
</VBox>
推荐阅读
- linux - 为什么 IBM MQ 在恢复日志中执行三次写入?
- android - 每次重新创建片段时,livedata 中的 onChanged 都会触发
- azure - 从 bot framework composer 重新部署 azure bot
- pandas - pandas csv阅读器产生错误的结果
- javascript - 如何设置阿波罗客户端:签入反应?
- javascript - 如何在 Vue.js 中加载数据之前延迟“未找到”错误
- ruby - 如何使用 Apps Script API 创建和执行函数
- node.js - 是否可以使用 Node.js 将地图直接保存到磁盘?
- javascript - *可能的未处理承诺拒绝(id:0):类型错误:未定义不是对象(评估'result.cancelled')云图像上传
- node.js - 为 Node.js 和 React.js 部署到 App Engine 设置 app.yaml 文件