【问题标题】:Label not being automatically updated with thread in javafx标签未使用 javafx 中的线程自动更新
【发布时间】:2018-04-19 10:31:56
【问题描述】:

其实我是java线程的初学者。为了我的学习目的,我创建了一个简单的程序。我不知道我错过了哪里。

代码:

package javaguithread;

import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class Controller {

    Thread t1;

    @FXML
    TextField input;

    @FXML
    Label output;

    @FXML
    private void addData() {
        output.setText(input.getText());
    }

    public void initialize() {

        t1 = new Thread(() -> {

            while (true) {
                System.out.println(input.getText());
                output.setText(input.getText());
            }
        });

        t1.start();
    }
}

它显示的错误是

at com.sun.javafx.tk.Toolkit.checkFxUserThread(
Toolkit.java:236)

更新

我尝试使用我创建的另一个类来初始化线程。她是我的密码。

package javathreadgui;

import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class Controller {

    private class GuiUpdater extends Task<Void> {

        Controller ctrl;

        GuiUpdater(Controller ctrl) {
            this.ctrl = ctrl;
        }

        @Override
        protected Void call() throws Exception {
            makeChanges();
            return null;
        }

        private void makeChanges(){
         while(true){
             Platform.runLater(() -> {
               ctrl.output.setText(ctrl.input.getText());  
             });

             System.out.println("test");

         }   
        }

    }

    @FXML
    TextField input;

    @FXML
    Label output;

    public void initialize() {
        System.out.println("Hello ");

        Task<Void> task = new GuiUpdater(this);

        Thread thread = new Thread(task);

        thread.setDaemon(true);
        thread.start();
    }

}

当我将控制台输出设置为

时效果很好
System.out.println("test");

否则 GUI 冻结。我能做些什么呢?

【问题讨论】:

  • 请发布完整的错误日志
  • 这只是一个错误。
  • 控制器初始化时为什么要在新线程下设置输出标签的文本??
  • 我不想用线程自动更新标签。我知道还有另一种不使用线程的方法。但只是为了我的学习目的,我正在使用线程。
  • 你实际上可以很容易地做到这一点,使用output.textProperty().bind(input.textProperty());

标签: java multithreading javafx


【解决方案1】:

任何 UI 更改都必须在 JavaFX 线程上进行。用下面的代码包装你的 setText() 调用:

Platform.runLater(new Runnable() {
      @Override public void run() {
           output.setText(input.getText());
      }
});

您可以搜索大量关于并发以及如何通过任务/线程更新 UI 的帖子。但是,如果您不想深入了解细节,您只需要知道每个 UI 更新都必须在 Platform.runLater(...) 调用中。

编辑:

这是一个可能对你有帮助的例子:

import java.util.Scanner;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;

public class LabelUpdateTest extends Application {

    private Label label;

    @Override
    public void start(Stage stage) throws Exception {
        label = new Label("Waiting for input..");
        stage.setScene(new Scene(label, 100, 100));
        stage.show();

        initInputThread();
    }

    private void initInputThread() {

        Scanner input = new Scanner(System.in);

        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() {
                while (true) {
                    String userInput = input.nextLine();

                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            label.setText("Input was : " + userInput);
                        }
                    });

                }
            }
        };

        Thread th = new Thread(task);
        th.setDaemon(true);
        th.start();
    }

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

【讨论】:

  • 我能得到关于最终 AtomicInteger 计数的线索 = new AtomicInteger(-1);
  • 好吧,我建议在这里阅读一些很棒的帖子:stackoverflow.com/questions/4818699/… 但是如果你只是想通过非 javaFX 线程更新你的 UI 不要想太多,你只需要调用 UI 更新在 Platform.runLater 中
  • 等一下。以前你让它在不同的线程上运行。现在你只需设置一个无限的 While 循环来更改标签的文本。我之前给你的代码是在非 JavaFX 线程(例如 Task、Thread 等)中更新 UI。
  • @suryabhusal 再次检查我的帖子。我添加了一个示例,您可以使用不同线程上的用户输入来更新标签的内容。
【解决方案2】:

随便用

Platform.runLater( () -> {
  output.setText(input.getText());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-29
    • 2017-05-05
    • 2016-01-02
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    相关资源
    最近更新 更多