我最近遇到了这个问题:
java.util.NoSuchElementException 线程“Thread-4”中的异常java.lang.IllegalStateException:不在FX应用程序线程上; currentThread = Thread-4
代码适用于jdk7但不适用于jdk8,代码如下:
public class myThread extends Thread {
TextArea ta;
String foo;
connect(String foo, TextArea ta){
this.ta = ta;
this.foo = foo;
}
@Override
public void run{
Scanner scanner = new Scanner(foo);
scanner.next();
ta.appendText(scanner.next());
}
}
然后我从这段代码中调用这个帖子:
public class myApp extends Application {
@Override
public void start(Stage stage) {
TextArea ta = new TextArea();
TextField tf = new TextField
Pane root = new Pane();
root.getChildren().addAll(ta,tf);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
tf.setOnAction((javafx.event.ActionEvent event) -> {
String foo = tf.getText();
tf.clear();
new myThread(foo,ta).start();
});
}
public static void main(String[] args) {
launch(args);
}
}
我想要做的就是从其他具有函数的线程更改控件的值/属性,就像在我的示例中一样,它扫描下一个字符串然后将它附加到TextArea。
为什么它适用于jdk7但不适用于jdk8?请。解释...
我已经完成了一些研究和解决方案,我来到这个JavaFX任务和服务,但是,我没有得到它们,并且没有在线的好例子。
请帮忙......谢谢......
答案 0 :(得分:4)
您的代码实际上也在JDK7上被破坏了。从后台线程(即不是来自FX应用程序线程)更改UI控件的状态是非法的。与几乎所有UI工具包一样,JavaFX使用单线程模型,并且不提供UI元素上的同步。因此,如果从FX Application Thread以外的线程更改或查看UI控件的状态,则代码很容易出现未指定和不可预测的行为。
在JavaFX 2.2及更早版本(随JDK 7提供)中,对于您的代码是否在正确的线程上执行的运行时检查较少。因此,您不会在JDK 7中获得运行时异常,但如上所述,您的代码存在错误,结果不确定。在JavaFX 8中,API得到了改进,因此(在大多数情况下)违反此规则会引发IllegalStateException
。 (这更好,因为你马上就知道出了什么问题。)
修复方法是更新FX应用程序线程上的UI控件:
final TextArea ta = new TextArea() ;
// ...
Platform.runLater(new Runnable() {
@Override
public void run() {
ta.appendText(scanner.next());
}
});
如果您现在只使用Java 8,则可以使用lambda表达式替换匿名内部类:
Platform.runLater(() -> ta.appendText(scanner.next()));
(并且不再需要声明ta
作为最终版,尽管仍有限制。)
答案 1 :(得分:2)
JavaFX场景图的所有更改都必须在FX-Application-Thread上进行。这意味着当你定义自己的线程时,它做了一些工作,然后想要将它的工作呈现给UI,你必须在FX-Application-Thread上做呈现部分。
在您的情况下,实现此目的的最简单方法是在Runnable中移动UI-Update部分(将结果附加到textarea),该部分必须从FX-Application-Thread启动。这可以通过在Platform.runLater()中调用新定义的Runnable来完成:
Platform.runLater( () -> ta.appendText(scanner.next()) );
老实说,我不确定,为什么你的方法在Java7中有效,因为afaik,这个行为没有任何改变。要获得有关JavaFX Tasks的更多信息,您可以查看Documentation。