繁体   English   中英

更新一个 JavaFX 状态 label

[英]Updating a JavaFX status label

我有一个使用模型/视图/控制器的 JavaFX 程序,我希望长时间运行 model 来更新视图上的状态 label。 我发现有人建议使用时间线class 来执行此操作。 我实现它时期望每一秒状态 Label 都会更新。 但是,仅显示最终状态。 我究竟做错了什么?

我的 controller 看起来像:

@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();
}

我的 model 看起来像:

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" />

您可以根据自己的目的使用Task ,它在后台线程中完成所有工作,这样 GUI 线程就不会被阻塞。 这是一个最小的例子:

Controller Class:

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();
    }
}

我的任务 Class:

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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM