我尝试根据耗时的任务更新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上运行。
答案 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();
}
在完成它的工作后似乎没有任何其他方法让它进入就绪状态。