JavaFx - 更新 GUI

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26554814/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 02:47:49  来源:igfitidea点击:

JavaFx - Updating GUI

javajavafx

提问by Indigo

All I wanted is to update a label as my program is running. I am reading some files and I wanted it to display the name of the file is was reading.

我想要的只是在我的程序运行时更新标签。我正在阅读一些文件,我希望它显示正在阅读的文件的名称。

However, it only displays the last file using the code below (basically GUI doesn't respond until the whole process is completed):

但是,它只使用下面的代码显示最后一个文件(在整个过程完成之前,GUI 基本上不会响应):

static Text m_status_update = new Text(); //I declared this outside the function so dont worry
m_status_update.setText("Currently reading " + file.getName());

I got around 4-5 files and I just want to display the name.

我有大约 4-5 个文件,我只想显示名称。

I saw a similar question Displaying changing values in JavaFx Label, the best answer recommended the following:

我看到了一个类似的问题Displaying changed values in JavaFx Label,最佳答案推荐如下:

Label myLabel = new Label("Start"); //I declared this outside the function so dont worry
myLabel.textProperty().bind(valueProperty);

However the valueProperty is a StringProperty and I am stuck converting a string into a string property.

但是 valueProperty 是一个 StringProperty 并且我被困在将字符串转换为字符串属性。

Also, I saw this Refresh label in JAVAFX, but the OP could update the label based on action. I really dont have any action going on?

另外,我在 JAVAFX 中看到了这个Refresh 标签,但 OP 可以根据操作更新标签。我真的没有任何动作吗?

采纳答案by James_D

If you run the entire process on the FX Application thread, then that is (effectively) the same thread that is being used to display the UI. If both the display of the UI, and your file iteration process are running in the same thread, only one can happen at once. So you prevent the UI from updating until the process is complete.

如果您在 FX 应用程序线程上运行整个进程,那么(实际上)就是用于显示 UI 的同一线程。如果 UI 的显示和您的文件迭代过程都在同一线程中运行,则一次只能发生一个。因此,您可以在该过程完成之前阻止 UI 更新。

Here's a simple example where I just pause for 250 milliseconds between each iteration (simulating reading a reasonably large file). One button launches this in the FX Application thread (notice how the UI is unresponsive while this runs - you can't type in the text field). The other button uses a Taskto run it in the background, properly scheduling updates to the UI on the FX Application thread.

这是一个简单的示例,我在每次迭代之间暂停 250 毫秒(模拟读取相当大的文件)。一个按钮在 FX 应用程序线程中启动它(注意 UI 在运行时没有响应 - 您不能在文本字段中输入)。另一个按钮使用 aTask在后台运行它,在 FX 应用程序线程上正确安排对 UI 的更新。

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;


public class UpdateTaskDemo extends Application {

    @Override
    public void start(Stage primaryStage) {
        Label label = new Label();
        Button runOnFXThreadButton = new Button("Update on FX Thread");
        Button runInTaskButton = new Button("Update in background Task");
        HBox buttons = new HBox(10, runOnFXThreadButton, runInTaskButton);
        buttons.setPadding(new Insets(10));
        VBox root = new VBox(10, label, buttons, new TextField());
        root.setPadding(new Insets(10));

        runOnFXThreadButton.setOnAction(event -> {
            for (int i=1; i<=10; i++) {
                label.setText("Count: "+i);
                try {
                    Thread.sleep(250);
                } catch (InterruptedException exc) {
                    throw new Error("Unexpected interruption");
                }
            }

        });

        runInTaskButton.setOnAction(event -> {
            Task<Void> task = new Task<Void>() {
                @Override 
                public Void call() throws Exception {
                    for (int i=1; i<=10; i++) {
                        updateMessage("Count: "+i);
                        Thread.sleep(250);
                    }
                    return null ;
                }
            };
            task.messageProperty().addListener((obs, oldMessage, newMessage) -> label.setText(newMessage));
            new Thread(task).start();
        });

        primaryStage.setScene(new Scene(root, 400, 225));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}