Javafx服务更新GUI对象状态

时间:2014-06-27 22:20:27

标签: javafx javafx-8

我尝试根据耗时的任务更新GUI状态。当我按下按钮时,我希望按钮处于非活动状态,并且光标会一直改变,直到作业完成。我已经提出了这个代码,主要是根据需要运行。

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class TestWait2 extends Application {

    @Override
    public void start(Stage primaryStage) {
        FlowPane root = new FlowPane();
        primaryStage.setScene(new Scene(root));

        MyService myService = new MyService();
        primaryStage.getScene().getRoot().cursorProperty()
                .bind(Bindings.when(myService.runningProperty())
                        .then(Cursor.WAIT).otherwise(Cursor.DEFAULT));

        Button startButton = new Button();
        startButton.setText("Button");
        startButton.disableProperty().bind(myService.runningProperty());
        root.getChildren().add(startButton);

        startButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                myService.start();
            }
        });

        primaryStage.show();
    }

    private class MyService extends Service<Void> {

        @Override
        protected Task<Void> createTask() {
            return new Task<Void>() {
                @Override
                protected Void call() throws Exception {
                    Thread.sleep(5000);
                    return null;
                }
            };
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

当我发布时,它第一次运行很棒。问题是如果我第二次点击按钮就会出错。

Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Can only start a Service in the READY state. Was in state SUCCEEDED

关于如何解决这个问题的任何想法?

我在Java 8u5上运行。

2 个答案:

答案 0 :(得分:1)

您的代码在myService.start();处于SUCCEEDED状态时尝试调用的问题(因为您已启动它一次)。

这是根据服务启动方法

的javadoc
  
      
  • 启动此服务。服务必须处于READY状态才能成功* *此呼叫。
  •   
  • 只应在FX应用程序线程上调用此方法。
  •   

要使代码正常工作,您需要调用myService.restart()。

由于您计划反复使用您的服务,因此您可以执行以下操作:

    startButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
               //replace this line
               // myService.start(); 
              //with this
               myService.restart(); 
            }
        });

答案 1 :(得分:0)

将此添加到程序似乎可以解决这个问题。

myService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
    @Override
    public void handle(WorkerStateEvent t) {
        myService.reset();
    }
});

我还发现我可以将以下内容直接添加到MyService类中。

@Override
protected void succeeded() {
    reset();
}

在完成它的工作后似乎没有任何其他方法让它进入就绪状态。