我正在嘗試構建一個進度條,該進度條正在更新,因爲我的應用程序正在檢索數據並將數據填充到GUI。我發現進度條會被重用很多,所以我決定創建自己的類。但是,我不相信我理解工人/任務或者多線程來創建可重用的情況。推薦的方法是創建一個可以偵聽應用程序線程並相應地更新欄的進度欄。這是我的嘗試:在JavaFx中構建多線程ProgressBar
// Simple Progress Bar View as Pop Up
public class ProgressIndicatorUtil{
@FXML
private ProgressBar progressBar;
@FXML
private Label statusLabel;
@FXML
private Button closeButton;
@FXML
private Label valueLabel;
private Worker worker;
private Stage stage;
public void setPopUpStage(Stage stage) {
this.stage = stage;
}
public void setWorker(Worker worker) {
this.worker = worker;
}
public void setLinkToMainPage(Object controller) {
((Task<String>) worker).setOnSucceeded(event -> stage.close());
((Task<String>) worker).setOnCancelled(event -> {
closeButton.setVisible(true);
stage.requestFocus();
statusLabel.setTextFill(Color.RED);}
);
valueLabel.textProperty().bind(Bindings.format("%5.1f%%", worker.progressProperty().multiply(100)));
progressBar.progressProperty().bind(worker.progressProperty());
statusLabel.textProperty().bind(worker.messageProperty());
}
@FXML
private void handleClose(ActionEvent e){
stage.close();
}
}
調用視圖彈出窗口並運行進度條線程的控制器。
public class MyController{
//Controller calling the view and disabling the main GUI
private void loadProgressBar(Worker worker){
try{
FXMLLoader loader = new FXMLLoader(getClass()
.getClassLoader().getResource("main/resources/fxml/ProgressBar.fxml"));
AnchorPane pane = (AnchorPane)loader.load();
Stage popUpStage = new Stage();
popUpStage.initModality(Modality.WINDOW_MODAL);
Scene scene = new Scene(pane);
popUpStage.setScene(scene);
ProgressIndicatorUtil controller = loader.getController();
controller.setPopUpStage(popUpStage);
controller.setWorker(worker);
controller.setLinkToMainPage(this);
mainPane.setDisable(true);
popUpStage.showingProperty().addListener((obs, hidden, showing) -> {
if(hidden) mainPane.setDisable(false);});
popUpStage.show();
}catch(IOException e){
e.printStackTrace();
}
}
private void runProgressBar(Worker worker) {
new Thread((Runnable) worker).start();
}
//A user action that runs the progress bar and GUI
@FXML
private void aBigProcessingEvent(ActionEvent event) {
Worker worker = new Task<String>(){
@Override
protected String call() throws Exception {
updateProgress(0, 3);
updateMessage("Clearing Data");
processingEvent01();
updateProgress(1, 3);
updateMessage("Retriving Data And Adding To List");
processingEvent02();
updateProgress(2, 3);
updateMessage("Populating Data");
processingEvent03();
updateProgress(3, 3);
return "Finished!";
}
};
loadProgressBar(worker);
runProgressBar(worker);
}
}
程序工作正常,在視覺上,但它拋出這樣一個異常(Not On FX Application Thread)和我的「processingEvent」方法運行Platform.runLater()會導致我的進度條,立即100%,但不會拋出異常。任何有關如何分離應用程序修改方法和工作者方法,同時保持連接到processingEvent方法的進程的建議?非常感謝。
您可以嘗試並創建一個Integer對象,然後將其傳遞給線程並在任務完成時增加。然後將您的進度設置爲integer /#任務的值。確保在訪問對象的引用時使用同步。 –
@MarcinDeszczynski你不能那樣做:它肯定會產生OP描述的那種IllegalStateException異常。綁定到任務的進度屬性並調用'updateProgress(...)'是完成此任務的正確方法。 –
這段代碼看起來很適合我;我無法測試它,因爲它不完整。哪一行會拋出'IllegalStateException'? 'processingEvent *()'方法有什麼作用?你應該在後臺線程中保留任何耗費時間的方法,但是包含所有更新「Platform.runLater(...)'中的UI的方法調用。(該'updateProgress'和'updateMessage'方法旨在從後臺線程調用;他們基本上處理對'Platform.runLater(...)'你的電話。) –