multithreading 如何避免不在 FX 应用线程上;currentThread = JavaFX 应用程序线程错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21083945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to avoid Not on FX application thread; currentThread = JavaFX Application Thread error?
提问by Rajesh
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.
下面的代码片段给了我错误Not on FX application thread; currentThread
= JavaFX
Application Thread
。这个应用程序在 java 1.7 中运行良好,但是当我将它移到 fx8 时,它现在给出了错误。当我第一次尝试启动应用程序时,它按预期工作。但是在关闭舞台并再次打开它后,它不起作用。
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.
错误也是模棱两可的。Not On fx application thread and current thread- javafx
application thread
如果当前线程是fx应用程序线程,那么不在fx应用程序线程上是什么意思。
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);
}
采纳答案by Rajesh
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 threaderror there.
Platform.setImplicitExit(false);
解决了我的问题。我认为他们更改了 JavaFX 8 中的实现,因此在 JavaFX 2 中没有任何问题的相同代码在那里给出了not an fx 应用程序线程错误。
回答by Martin Pfeffer
Calling
打电话
Platform.runLater(new Runnable(){
// ...
});
will fix it.
将修复它。
回答by vinay
This happened with me when i was modifying UI element from task in javafx 2 like listview elements.A Task Which Modifies The Scene Graphhelped me to solve the issue i.e. updating UI elements by
当我从 javafx 2 中的任务修改 UI 元素(如 listview 元素)时,这发生在我身上。修改场景图的任务帮助我解决了这个问题,即通过以下方式更新 UI 元素
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;
}
};
回答by arturvt
It should happens when you try to change some component UI, like a label text. Running like that works always:
当您尝试更改某些组件 UI(例如标签文本)时,应该会发生这种情况。像这样运行总是有效的:
@FXML Label myLabel;
Platform.runLater(new Runnable(){
myLabel.setText("some text");
});
回答by diego matos - keke
You can change of Form or go to another view or fxml with this in any part of your code :
您可以在代码的任何部分更改表单或转到另一个视图或 fxml:
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();
}
}
}
回答by WillBD
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.
它没有在上面的代码中明确显示,但我相当确定正在发生的是,您正在应用程序(主)javafx 线程之外的某个地方创建一个线程,然后您尝试对 javafx 对象执行操作(例如关闭,打开窗户等)在第二个线程上。这是绝对不允许的,因为只有主线程可以直接控制 javafx 对象。如果这成为您的程序的要求,您需要将第二个线程用于计算等其他事情。您必须使用某种形式的消息传递让另一个线程知道您想要执行任何 javafx 操作。
回答by Benson Kiprono
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:
运行它给出了“不在 fx 应用程序上”。通过在我的任务中添加 Platform.runLater(),解决了这个问题。现在,这就是我目前拥有代码的方式:
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.
我希望这会帮助您解决问题。干杯。