Reputation: 2277
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);
}
Upvotes: 69
Views: 118716
Reputation: 12627
Calling
Platform.runLater(new Runnable() {
@Override
public void run() {
// do your GUI stuff here
}
});
will fix it.
Upvotes: 107
Reputation: 129
I experienced the same problem while trying to add a splash screen for my program. This is how my code was
CircleTest pForm = new CircleTest();
Task<Void> task = new Task<Void>() {
@Override
public Void call() {
try {
FXMLLoader loader = new FXMLLoader(
Main.class.getResource("/newRegistration/HomePage.fxml"));
AnchorPane page = (AnchorPane) loader
.load();
dialogStagee.getIcons().add(new Image("/piks/showthumb.png"));
dialogStagee.setTitle("WALGOTECH SOLUTIONS: 0703445354");
dialogStagee.initModality(Modality.APPLICATION_MODAL);
Scene scene = new Scene(page);
dialogStagee.setScene(scene);
HomePageController controller = loader.getController();
controller.setDialogStage(dialogStagee);
dialogStagee.setMaximized(true);
dialogStagee.initStyle(StageStyle.UNDECORATED);
conn.prepareStatement(
"INSERT INTO `logs`(`date`,`user`,`Terminal`,`Action`)"
+ " VALUES ('"
+ (java.time.LocalDate.now()
+ " "
+ java.time.LocalTime.now().getHour()
+ ":"
+ java.time.LocalTime.now().getMinute()
+ ":" + java.time.LocalTime.now().getSecond())
+ "',"
+ "'"
+ DbConnector.getMyVariablepatientvameloginCategory()
.split("as")[1]
+ "',"
+ "'"
+ StartPageController.hostname
+ "',"
+ " 'Logged in into Registration')")
.execute();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
};
pForm.activateProgressBar(task);
task.setOnSucceeded(event -> {
dialogStagee.show();
try {
} catch (Exception e) {
}
pForm.getDialogStage().close();
});
pForm.getDialogStage().show();
dialogStage.close();
Thread thread = new Thread(task);
thread.start();
Running this gave a 'not on fx application'. By adding Platform.runLater() inside my task, that solved the issue. Now, this is how I currently have my code:
CircleTest pForm = new CircleTest();
Task<Void> task = new Task<Void>() {
@Override
public Void call() {
Platform.runLater(new Runnable() {
@Override
public void run() {
try {
FXMLLoader loader = new FXMLLoader(
Main.class
.getResource("/newRegistration/HomePage.fxml"));
AnchorPane page = (AnchorPane) loader
.load();
dialogStagee.getIcons().add(
new Image("/piks/showthumb.png"));
dialogStagee
.setTitle("WALGOTECH SOLUTIONS: 0703445354");
dialogStagee
.initModality(Modality.APPLICATION_MODAL);
Scene scene = new Scene(page);
dialogStagee.setScene(scene);
HomePageController controller = loader
.getController();
controller.setDialogStage(dialogStagee);
dialogStagee.setMaximized(true);
dialogStagee.initStyle(StageStyle.UNDECORATED);
conn.prepareStatement(
"INSERT INTO `logs`(`date`,`user`,`Terminal`,`Action`)"
+ " VALUES ('"
+ (java.time.LocalDate.now()
+ " "
+ java.time.LocalTime.now().getHour()
+ ":"
+ java.time.LocalTime.now().getMinute()
+ ":" + java.time.LocalTime.now().getSecond())
+ "',"
+ "'"
+ DbConnector.getMyVariablepatientvameloginCategory()
.split("as")[1]
+ "',"
+ "'"
+ StartPageController.hostname
+ "',"
+ " 'Logged in into Registration')")
.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
});
return null;
}
};
pForm.activateProgressBar(task);
task.setOnSucceeded(event -> {
dialogStagee.show();
try {
} catch (Exception e) {
}
pForm.getDialogStage().close();
});
pForm.getDialogStage().show();
dialogStage.close();
// dialogStage.setDisable(true);
Thread thread = new Thread(task);
thread.start();
I hope this will help you solve the problem. Cheers.
Upvotes: 1
Reputation: 2109
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();
}
}
}
Upvotes: 7
Reputation: 781
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");
});
Upvotes: 24
Reputation: 1121
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;
}
};
Upvotes: 44
Reputation: 2277
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.
Upvotes: 19
Reputation: 1919
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.
Upvotes: 5