How to avoid Not on FX application thread; current

2019-01-04 02:01发布

Below code snippets is giving me error Not on FX application thread; currentThread=JavaFX Application Thread.This application was working fine in java 1.7 but when i moved it to fx8 it is now giving error. when I start the application on my 1st attempt it is working as intended .But after closing the stage and opening it again it is not working.

The error is also ambiguous Not On fx application thread and current thread- javafx application thread.What did it mean by not on fx application thread if the current thread is a fx application thread.

      progressDialog = createProgressDialog(service);
        progressDialog.show();
        progressDialog.setOnCloseRequest(new EventHandler<WindowEvent>() {
          @Override
          public void handle(WindowEvent event) {
            // if (service.isRunning()) {
            // service.cancel();
            progressDialog.close();
            // }
          }
        });

      }

      @SuppressWarnings("unchecked")
      private Stage createProgressDialog(final Service<IStatus> service) {
        stage = new Stage();

        URL url = FileLocator.find(Activator.getDefault().getBundle(),
            new Path("icons/xxx_16x16.png"), null); //$NON-NLS-1$
        stage.getIcons().add(new Image(url.getFile()));
        stage.setTitle("Downloading ..."); //$NON-NLS-1$
        // Creating StackPane
        stage.initModality(Modality.WINDOW_MODAL);
}

6条回答
孤傲高冷的网名
2楼-- · 2019-01-04 02:31

This happened with me when i was modifying UI element from task in javafx 2 like listview elements.A Task Which Modifies The Scene Graph helped me to solve the issue i.e. updating UI elements by

 final ListView<String> group = new ListView ();

 Task<Void> task = new Task<Void>() {

     @Override protected Void call() throws Exception {

         group.getItems().clear();  

          for (int i=0; i<100; i++) {                
             Platform.runLater(new Runnable() {
                 @Override public void run() {
                     group.getItems.add(i);
                 }
             });
         }
         return null;
     }
 };
查看更多
够拽才男人
3楼-- · 2019-01-04 02:33

Calling

Platform.runLater(new Runnable(){
// ...
});

will fix it, too.

查看更多
ら.Afraid
4楼-- · 2019-01-04 02:38

It should happens when you try to change some component UI, like a label text. Running like that works always:

@FXML Label myLabel;

Platform.runLater(new Runnable(){
   myLabel.setText("some text");
});
查看更多
淡お忘
5楼-- · 2019-01-04 02:41

You can change of Form or go to another view or fxml with this in any part of your code :

Platform.runLater(() -> {
                            try {
                                Stage st = new Stage();
                                Parent sceneMain = FXMLLoader.load(getClass().getResource("/com/load/free/form/LoadFile.fxml"));
                                Scene scene = new Scene(sceneMain);
                                st.setScene(scene);
                                st.setMaximized(true);
                                st.setTitle("load");
                                st.show();
                            } catch (IOException ex) {
                                Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        });

My Example in my Controller :

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;


public class LoginController implements Initializable {

    @FXML
    private TextField txtUser;

    @FXML
    private TextField txtPassword;

    @FXML
    private Hyperlink urlForgetPassword;

    @FXML
    private Label lblError;

    @Override
    public void initialize(URL url, ResourceBundle rb) {

    }

    public void isLoginAction(ActionEvent event) {
        String message = "Ingrese ";
        boolean isEmtpy = false;

        if (txtUser.getText().trim().isEmpty()) {
            message += "usuario y ";
            isEmtpy = true;
        }

        if (txtPassword.getText().trim().isEmpty()) {
            message += "contraseña  ";
            isEmtpy = true;
        }
        isEmtpy = false;
        if (isEmtpy) {
            message = message.substring(0, message.length() - 2);
            lblError.getStyleClass().remove("message_process");
            lblError.getStyleClass().add("message_error");
            lblError.setText(message);
        } else {
            lblError.getStyleClass().add("message_process");
            lblError.getStyleClass().remove("message_error");
            Task task = new Task<Void>() {
                @Override
                protected Void call() throws Exception {
                    updateMessage("Procesando...");
                    System.out.println("Asignando DATOS DE PRUEBA ");
                    String passEnc = Encripta.encriptar(txtPassword.getText(), Encripta.HASH_SHA1);
                    int typeRest = new RestConnection().getConnectionUser(txtUser.getText(), passEnc);
                    if (typeRest == 1) {
                        //Load Another form
                        Platform.runLater(() -> {
                            try {
                                Stage st = new Stage();
                                Parent sceneMain = FXMLLoader.load(getClass().getResource("/com/load/free/form/LoadFile.fxml"));
                                Scene scene = new Scene(sceneMain);
                                st.setScene(scene);
                                st.setMaximized(true);
                                st.setTitle("");
                                st.show();
                            } catch (IOException ex) {
                                Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        });

                    } else {
                        lblError.getStyleClass().remove("message_process");
                        lblError.getStyleClass().add("message_error");
                        updateMessage("Usuario y/o contraseña incorrectos");
                    }
                    return null;
                }
            };

            lblError.textProperty().bind(task.messageProperty());
            new Thread(task).start();

        }

    }

}
查看更多
该账号已被封号
6楼-- · 2019-01-04 02:46

It's not shown explicitly in the code above, but what I'm fairly sure is happening is that somewhere you are creating a thread outside of the application (main) javafx thread, and then you are trying to preform operations on javafx objects (like closing, opening windows, etc.) on the SECOND thread. This is strictly not allowed, as only the main thread can control javafx objects directly. If this becomes a requirement of your program that you need to use the second thread for other things like computations, etc, etc. You must use some form of message passing to let the other thread know that you want to do whatever javafx action.

查看更多
看我几分像从前
7楼-- · 2019-01-04 02:52

Platform.setImplicitExit(false); solved my problem. I think they changed the implementation in JavaFX 8, so the same code that works without any issue in JavaFX 2 gives the not an fx application thread error there.

查看更多
登录 后发表回答