这个问题已经被问到了,但是我已经提出了这个问题。设想。我有一个有2个场景的程序。首先打开scene1,这是连接数据库的场景。有一个名为Status的标签,当建立连接时(通过单击COnnect按钮),该标签应从“Disconnected”变为“Connected”。所以我做了一个函数来接受onClick事件的“连接”按钮。此函数在控制器类中声明和定义(我使用场景构建器进行fmxl设计)。所以基本上我想从控制器类内部的连接函数(方法)将状态更改为“COnnected”(status.setText(“Connected”))。但是,当我这样做时,文本在建立连接后不会立即更改,但是当场景即将关闭时它会改变,我即将把场景更改为新场景...我在互联网上阅读我看到我应该使用Platform.runLater和线程,所以我尝试了:
private void changeSC() throws IOException, InterruptedException, SQLException
{
dbConnect();
Thread thrd = new Thread() {
public void run() {
Platform.runLater(new Runnable() {
@Override public void run() {
status.setText("Connected");
status.setTextFill(Color.GREEN);
}});
}
};
thrd.start();
//pb.setProgress(1.0);
Parent root = FXMLLoader.load(getClass().getResource("Design.fxml"));
Scene primary = new Scene(root,1024,768);
primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
System.out.println("Text changing to COnnected");
status.setTextFill(Color.GREEN);
Thread.sleep(2000);
Main.window.setScene(primary);
}
changeSC是单击“连接”按钮时执行的功能。这是我的旧版本,也不起作用:
private void changeSC() throws IOException, InterruptedException, SQLException
{
dbConnect();
status.setText("Connected");
status.setTextFill(Color.GREEN);
//pb.setProgress(1.0);
Parent root = FXMLLoader.load(getClass().getResource("Design.fxml"));
Scene primary = new Scene(root,1024,768);
primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
System.out.println("Text changing to COnnected");
status.setTextFill(Color.GREEN);
Thread.sleep(2000);
Main.window.setScene(primary);
}
问题在于文本应该更改为“已连接”。当我的场景即将被切换时它会改变....
答案 0 :(得分:3)
如果您有一些长时间运行的操作,则需要使用Task
。否则,当从JavaFX应用程序线程调用该操作时,它将阻止GUI。
如果要从Task
更新GUI,则必须使用Platform.runlater
,这将运行JavaFX应用程序线程上的代码:
Platform.runlater
总是要在JavaFx线程上执行GUI Nodes
的更新。
当您在status
的{{1}}内更新Listener
时,它应该有效。
button
如果 button.setOnAction(evt -> {
dbConnect();
status.setText("Connected");
// ...
});
需要一些时间,您可以使用dbConnect()
:
Task
答案 1 :(得分:0)
由于您要连接到数据库,因此应该使用Task
或Service
将此代码放在后台运行,以使GUI线程响应用户输入。请记住,只有在GUI线程中,您才能更新视图状态(更改案例中文本的值)。您可以使用java Thread
并使用Platform.runLater
,这意味着内部代码计划由GUI Thread进行,但在您的情况下,您使用的方式是错误的。首先,连接数据库的逻辑应该在线程的方法run
内,一旦方法完成,设置文本的值并做任何你想要的事情。此外,您还需要在完成所有过程后显示新的Scene
,以便让用户有机会查看文本中的更改。您可以通过以下方式更改代码:
private void changeSC() throws IOException, InterruptedException, SQLException
{
Thread thrd = new Thread() {
public void run() {
dbConnect();
Platform.runLater(new Runnable() {
@Override public void run() {
status.setText("Connected");
status.setTextFill(Color.GREEN);
//pb.setProgress(1.0);
Parent root = FXMLLoader.load(getClass().getResource("Design.fxml"));
Scene primary = new Scene(root,1024,768);
primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
System.out.println("Text changing to COnnected");
status.setTextFill(Color.GREEN);
Main.window.setScene(primary);
}
});
}
};
thrd.start();
}
如果您选择使用Task
,则无需明确处理Platform.runLater
。您只需要创建一个任务(类Task
的实现),将其包装在java Thread
中,启动它并为不同的事件设置处理程序(例如:setOnSucceeded
)。这是使用Task
的代码:
private void changeSC() throws IOException, InterruptedException, SQLException
{
Task<Void> task = new Task<Void>(){
@Overrdie
protected Void call() {
dbConnect();
return null;
}
};
//start Task
Thread t = new Thread(task);
t.setDaemon(true); // thread will not prevent application shutdown
t.start();
task.setOnSucceeded(event -> {
Parent root = FXMLLoader.load(getClass().getResource("Design.fxml"));
Scene primary = new Scene(root,1024,768);
primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
System.out.println("Text changing to COnnected");
status.setTextFill(Color.GREEN);
Main.window.setScene(primary);
});
}
答案 2 :(得分:-2)
好吧我通过设置task.SetonFailed()来修复它:)