简体   繁体   中英

JavaFX works fine on jdk7 but not on jdk8: Not on FX application thread

I recently encountered this problem:

java.util.NoSuchElementException Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4

The code works on jdk7 but not on jdk8, the code look like this:

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());
    }
}

Then i call this thread from this code:

    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);
        }
    }

All I want to do is change the values/properties of the controls from other threads which have functions just like in my example it scans for the next string then append it to the TextArea.

Why it works on jdk7 but not on jdk8? pls. explain...

I've done some research and the solution i came up to this JavaFX task and service but, i dont get them and there are no good examples online.

Pls help... Thanks...

Your code is actually broken on JDK7 too. It is illegal to change the state of UI controls from a background thread (ie not from the FX Application Thread). Like almost all UI toolkits, JavaFX uses a single threaded model, and provides no synchronization on UI elements. Consequently if you change or view the state of a UI control from a thread other than the FX Application Thread, your code is prone to unspecified and unpredictable behavior.

In JavaFX 2.2 and earlier (shipping with JDK 7), there were fewer runtime checks on whether your code was being executed on the correct thread. So you don't get the runtime exception in JDK 7, but as mentioned your code is buggy and the results are not deterministic. In JavaFX 8, the API was improved so that (in most cases) violating this rule throws an IllegalStateException . (This is better as you know immediately something is wrong.)

The fix is to update your UI controls on the FX Application Thread:

final TextArea ta = new TextArea() ;

// ...

Platform.runLater(new Runnable() {
    @Override
    public void run() {
        ta.appendText(scanner.next());
    }
});

If you are now using Java 8 exclusively, you can replace the anonymous inner class with a lambda expression:

Platform.runLater(() -> ta.appendText(scanner.next()));

(and there's no longer any need to declare ta as final, though there are still restrictions).

All changes to the scene graph of JavaFX have to happen on the FX-Application-Thread. This means when you define your own thread, which does some work and then wants to present its work to the UI, you have to do the presenting part on the FX-Application-Thread.

In your case the easiest way to achieve this is moving the UI-Update part (appending the result to the textarea) within a Runnable, which has to be started from the FX-Application-Thread. This can be done by calling the new defined Runnable within Platform.runLater():

Platform.runLater( () -> ta.appendText(scanner.next()) );

Honestly I am not sure, why your approach has worked in Java7, since afaik, nothing changed concerning this behaviour. To get more Information about JavaFX Tasks you can have a look at the Documentation .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM