0

I want to open a new window (Stage) in javafx from an external Thread (not from the principal Thread). my code bellow is not working, please help me.

This is my java code :

public void login(ActionEvent event)
{       
    Task task = new javafx.concurrent.Task<Void>()
    {
            @Override
            protected Void call() throws Exception 
            {
                loader.setVisible(true);
                if(Compte.login(username.getText(), password.getText()))
                {
                    Parent root = FXMLLoader.load(getClass().getResource("/views/PrincipalFram.fxml"));
                    Scene scene = new Scene(root);
                    Stage stage = new Stage();
                    stage.setScene(scene);
                    stage.setTitle("My Title");
                    stage.show();
                }
                else
                {
                    //TODO 
                }
                return null;
            }

            @Override
            protected void succeeded() 
            {
                loader.setVisible(false);
            }

            @Override
            protected void failed() 
            {
                loader.setVisible(false);
            }
    };
    Thread thread = new Thread(task);
    thread.setDaemon(true);
    thread.start();
}
M.Lamine Lalmi
  • 78
  • 1
  • 2
  • 12
  • Why are you using a background thread here? What is it here that takes time to execute? See if the general comments on multithreading in JavaFX [here](http://stackoverflow.com/questions/30249493/using-threads-to-make-database-requests) help. – James_D May 10 '17 at 16:22
  • I have a login button that send a request to my database which is on a server. so it's better to do it inside a thread. – M.Lamine Lalmi May 10 '17 at 16:26
  • OK, but then *only* that should be done inside the background thread. The UI work must be done on the FX Application Thread. – James_D May 10 '17 at 16:27

1 Answers1

1

Perform only the time-consuming work on the background thread. All UI work must be done on the FX Application Thread. (The documentation for Stage explicitly states that "Stage objects must be constructed and modified on the FX Application Thread".) So you should do:

public void login(ActionEvent event) {   

    Task<Boolean> loginTask = new Task<Boolean>() {
        @Override
        protected Boolean call() throws Exception {
            return Compte.login(username.getText(), password.getText());
        }
    };

    loginTask.setOnSucceeded(e -> {

        if (loginTask.getValue()) {
            Parent root = FXMLLoader.load(getClass().getResource("/views/PrincipalFram.fxml"));
            Scene scene = new Scene(root);
            Stage stage = new Stage();
            stage.setScene(scene);
            stage.setTitle("My Title");
            stage.show();
        } else {
            //TODO 
        }
        loader.setVisible(false);
    });

    loginTask.setOnFailed(e -> {
        loader.setVisible(false);
    });

    Thread thread = new Thread(task);
    thread.setDaemon(true);
    loader.setVisible(true);
    thread.start();
}
James_D
  • 201,275
  • 16
  • 291
  • 322