对于学校项目,我正在为PLC编程一点可视化。因此,我有一个mySQL数据库,其中包含所有信息。目前,当我单击一个Button时,程序将连接到数据库并在ArrayList中获取它。然后它检查ArrayList中的信息并将Data放入ListView。
问题是,我想让程序在服务中执行此操作。正如我所说,GUI取决于ArrayList。我无法更改服务中的GUI,因为此时出现此异常
Sep 02, 2016 9:19:02 PM javafx.concurrent.Service lambda$static$488
WARNING: Uncaught throwable in javafx concurrent thread pool
java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(Unknown Source)
at javafx.scene.Parent$2.onProposedChange(Unknown Source)
at com.sun.javafx.collections.VetoableListDecorator.setAll(Unknown Source)
at com.sun.javafx.collections.VetoableListDecorator.setAll(Unknown Source)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(Unknown Source)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(Unknown Source)
at com.sun.javafx.scene.control.skin.LabelSkin.handleControlPropertyChanged(Unknown Source)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$61(Unknown Source)
at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(Unknown Source)
at javafx.beans.value.WeakChangeListener.changed(Unknown Source)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(Unknown Source)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(Unknown Source)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(Unknown Source)
at javafx.beans.property.StringPropertyBase.markInvalid(Unknown Source)
at javafx.beans.property.StringPropertyBase.set(Unknown Source)
at javafx.beans.property.StringPropertyBase.set(Unknown Source)
at javafx.beans.property.StringProperty.setValue(Unknown Source)
at javafx.scene.control.Labeled.setText(Unknown Source)
at application.Controller$1$1.call(Controller.java:290)
at application.Controller$1$1.call(Controller.java:1)
at javafx.concurrent.Task$TaskCallable.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at javafx.concurrent.Service.lambda$null$493(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at javafx.concurrent.Service.lambda$executeTask$494(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
我的第一个想法是仅提取服务中的SQL内容,然后通过方法获取数据
service.getValue();
但问题是我不知道服务何时完成获取数据,因为目前数据为空。
答案 0 :(得分:3)
基本上,你想运行一些进程并返回一些值,
当然Service
指甲。这就是我如何处理我的案例,它完美无缺。
Service process = new Service() {
@Override
protected Task createTask() {
return new Task() {
@Override
protected ObjectX call() throws Exception {
updateMessage("Some message that may change with execution");
updateProgress( workDone, totalWork );
return ObjectX;
}
};
}
};
process.setOnSucceeded( e -> {
ObjectX processValue = (ObjectX)process.getValue();
// TODO, . . .
// You can modify any GUI element from here...
// ...with the values you got from the service
});
process.start();
需要注意的事项
protected ObjectX call()
可以返回任何类型的对象。只要确保它是一个对象而不是一个原始类型。您可以在此过程中填充一些GUI元素并将其作为对象返回,例如。 protected VBox call()
。 。 。 。 return my_vbox;
ObjectX processValue = (ObjectX)processList.getValue();
=>您应该将从Service
获得的值转换回要使用的对象。
如果只是Object
,您可能没有。但我怀疑你是否必须只使用Object
。processList.setOnFailed()
,processList.setOnRunning()
,processList.setOnCancelled()
,processList.setOnScheduled()
,您还可以将一些GUI元素绑定到某些Thread属性,例如
label.textProperty.bind( process.messageProperty ); // messageProperty is a StringProperty
progressBar.progressProperty.bind( process.progressProperty )
确保在调用process.start()
之前已创建并启动了所有进一步增强流程的方法;在你开始这个过程之前没有任何事情发生。
我希望这会有所帮助
答案 1 :(得分:2)
Service
类提供的方法让您知道它是取消,成功还是失败。
在扩展服务的类的构造函数中使用以下方法:
// succeeded?
this.setOnSucceeded(s -> {
// ...
});
// failed
this.setOnFailed(f -> {
// ...
});
// cancelled?
this.setOnCancelled(c -> {
// ...
});
还记得使用updateProgress(current,maximum)
;所以你知道它在执行过程中发生了什么。
以下是一个完整的例子:
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class ExampleService extends Service<Boolean> {
/**
* Constructor
*/
public ExampleService() {
// succeeded?
this.setOnSucceeded(s -> {
// ...
});
// failed
this.setOnFailed(f -> {
// ...
});
// cancelled?
this.setOnCancelled(c -> {
// ...
});
}
@Override
protected Task<Boolean> createTask() {
return new Task<Boolean>(){
@Override
protected Boolean call() throws Exception {
boolean result = false;
//your code
//.......
//updateProgress(current,total)
return result;
}
};
}
}