Vladimir Ushakov
Vladimir Ushakov

Reputation: 75

IllegalStateException while creating a stage in another thread

I have a problem with opening one more stage in another thread. No exceptions appears if I'm opening this stage in the same thread.

void hashMapDeclaration(){
    actions2methods.put("NEW", new Runnable() {@Override public void run() { newNetCreation(); }});
    actions2methods.put("LOAD", new Runnable() {@Override public void run() { loadNetState(); }});
    ......  //other hashes
}

HBox buttonBuilder(double spacing,double layoutX,String... bNames){
    HBox lBar = new HBox(10);
    .... //some code
    for(final String text : bNames){ //in my case text variable value is "NEW" so it should run method newNetCreation
        Button newButton = new Button();
        newButton.setText(text);
        .... //code
        newButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent paramT) {
                Thread t;
                EventQueue.isDispatchThread();
                t = new Thread(actions2methods.get(text));
                t.start(); // Start the thread 
                System.out.println("button pressed");
            }
        });
        lBar.getChildren().add(newButton);
    }
    return lBar;
}

void newNetCreation(){
    final Stage dialogStage = new Stage();
    final TextField textField;
    dialogStage.initOwner(stage);
    dialogStage.initModality(Modality.WINDOW_MODAL);   
    dialogStage.setFullScreen(false);
    dialogStage.setResizable(false);
    dialogStage.setScene(SceneBuilder
        .create()
        .fill(Color.web("#dddddd"))
        .root(textField = TextFieldBuilder
                            .create()
                            .promptText("Enter user name")
                            .prefColumnCount(16)
                            .build()
        )
        .build()
    );
    textField.textProperty().addListener(new ChangeListener() {
        public void changed(ObservableValue ov, Object oldValue, Object newValue) {
            System.out.println("TextField text is: " + textField.getText());
        }
    });
    dialogStage.show();
    System.out.println("new net");
}

Method newNetCreation is the one that cause the problem. All actions in my program are store in a HashMap. Method buttonBuilder creates the new thread and should launch methods according to variable value and in my case he must call newNetCreation method, but when he tries, the following exception occurs:

Exception in thread "Thread-3" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(Unknown Source)
at javafx.stage.Stage.<init>(Unknown Source)
at javafx.stage.Stage.<init>(Unknown Source)
at projavafx.starterapp.ui.StarterAppMain.newNetCreation(StarterAppMain.java:400)
at projavafx.starterapp.ui.StarterAppMain$7.run(StarterAppMain.java:354)
at java.lang.Thread.run(Thread.java:722)

Upvotes: 3

Views: 7262

Answers (1)

Sergey Grinev
Sergey Grinev

Reputation: 34498

All UI operation for JavaFX should be perfromed on FX application thread.

Here is your code:

  Thread t; 
  t = new Thread(actions2methods.get(text));
  t.start(); // Start the thread 

t is thread which you runs your method on. It's obviously not FX thread as stated in log your provided: java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3

If you want to run Runnable on FX thread, use next code:

  Platform.runLater(actions2methods.get(text));

Upvotes: 8

Related Questions