Javafx Task - 从方法更新进度

Javafx Task - update progress from a method

在 JavaFX 应用程序中,我希望根据我在另一个 class 中实现的一些工作逻辑来更新状态栏。

我不知道如何将我希望将工作逻辑传递给方法(而不是将其写在任务中)与了解工作进度百分比相结合。

这是带有任务的控制器示例:

public class FXMLDocumentController implements Initializable {

    @FXML private Label label;    
    @FXML ProgressBar progressBar;

    @FXML
    private void handleButtonAction(ActionEvent event) {

        Service<Void> myService = new Service<Void>() {

            @Override
            protected Task<Void> createTask() {
                return new Task<Void>() {

                    @Override
                    protected Void call() throws Exception {
                        try {
                            DatabaseFunctionality.performWorkOnDb();

                            //updateProgress(1, 1);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
                        }

                        return null;
                    }
                }; 
            }            
        };

        progressBar.progressProperty().bind(myService.progressProperty());
        myService.restart();
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }        
}

这是帮手class:

public class DatabaseFunctionality {

    public static void performWorkOnDb () throws InterruptedException {
        for (int i = 1; i <= 100; i++) {
            System.out.println("i=" + i);
            Thread.sleep(100);

            //Update progress
        }        
    }    
}

谢谢

这里有几个选项。一种是按照 Uluk 的建议去做,并在你的 DatabaseFunctionality class:

中公开一个可观察的 属性
public class DatabaseFunctionality {

    private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper();

    public double getProgress() {
        return progressProperty().get();
    }

    public ReadOnlyDoubleProperty progressProperty() {
        return progress ;
    }

    public void performWorkOnDb() throws Exception {
        for (int i = 1; i <= 100; i++) {
            System.out.println("i=" + i);
            Thread.sleep(100);

            progress.set(1.0*i / 100);
        }        
    }   
}

现在在您的 Task 中,您可以观察到 属性 并更新任务的进度:

Service<Void> myService = new Service<Void>() {

    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {

            @Override
            protected Void call() throws Exception {
                try {
                    DatabaseFunctionality dbFunc = new DatabaseFunctionality();
                    dbFunc.progressProperty().addListener((obs, oldProgress, newProgress) -> 
                        updateProgress(newProgress.doubleValue(), 1));

                    dbaseFunc.performWorkOnDb();

                } catch (InterruptedException ex) {
                    Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
                }

                return null;
            }
        }; 
    }            
};

另一种选择(如果您不希望数据访问对象依赖于 JavaFX 属性 API)是向数据访问对象传递回调以更新进度。 BiConsumer<Integer, Integer> 适用于此:

public class DatabaseFunctionality {

    private BiConsumer<Integer, Integer> progressUpdate ;

    public void setProgressUpdate(BiConsumer<Integer, Integer> progressUpdate) {
        this.progressUpdate = progressUpdate ;
    }

    public void performWorkOnDb() throws Exception {
        for (int i = 1; i <= 100; i++) {
            System.out.println("i=" + i);
            Thread.sleep(100);

            if (progressUpdate != null) {
                progressUpdate.accept(i, 100);
            }
        }        
    }   
}

然后

Service<Void> myService = new Service<Void>() {

    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {

            @Override
            protected Void call() throws Exception {
                try {
                    DatabaseFunctionality dbFunc = new DatabaseFunctionality();
                    dbFunc.setProgressUpdate((workDone, totalWork) -> 
                        updateProgress(workDone, totalWork));

                    dbaseFunc.performWorkOnDb();

                } catch (InterruptedException ex) {
                    Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
                }

                return null;
            }
        }; 
    }            
};
public void initialize() {
    Task<Void> task = new Task<>() {
        @Override
        protected Void call() {
            try {
                Double d = 0.0;
                for (int i = 1; i <= 100; i++) {
                    Thread.sleep(100);
                    d = 1.0 * i / 100;
                    updateProgress(d, 1);
                }
            }  catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    };

    task.progressProperty().addListener((obs, oldProgress, newProgress) -> {
        System.out.println((newProgress.doubleValue() * 100) + "% completed");
    });
    new Thread(task).start();
}