当前位置: 首页 > 知识库问答 >
问题:

JavaFX:在FXML窗口上有后台任务更新标签文本吗?

平元明
2023-03-14

我的目标是创建一个javaFX窗口,当单击该窗口时,它将增加单例类的计数器。后台任务应该读取单例中的值,并将其显示在同一窗口中。下面是单身汉。

辛格尔顿。爪哇:

public class Singleton {
    private static Singleton singleton = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return singleton;
    }

    //=====================================

    private int count = 0;

    public void increment() {
        count++;
        System.out.println(count);
    }

    public int getCount() {
        return count;
    }

}

为了创建后台线程,我尝试通过JavaFX提供的initialize()方法创建一个任务。可初始化,但这会产生“不在FX应用程序线程上”错误。下面是获取FXML并启动窗口的主窗口。

主要的爪哇:

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
            primaryStage.setTitle("Hello World");

            Scene scene = new Scene(root,400,400);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();

        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

Sample.fxml-这里是我定义窗口结构的地方。请注意第一个标签的fx: id=“计数器”。

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="199.0" prefWidth="230.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
   <children>
      <AnchorPane layoutX="22.0" layoutY="9.0" prefHeight="182.0" prefWidth="186.0">
         <children>
            <Button layoutX="14.0" layoutY="76.0" mnemonicParsing="false" onAction="#buttonClicked" text="Increment" />
            <Label fx:id="counter" layoutX="131.0" layoutY="81.0" text="0" />
            <Label layoutX="28.0" layoutY="34.0" text="First JavaFX Project" />
         </children>
      </AnchorPane>
   </children>
</Pane>

Controller.java-最后是控制器。初始化函数创建一个新线程来运行获取计数器值所需的任务,但它不能编辑原始窗口。

public class Controller implements Initializable {

    // Links to Singleton classes
    private Singleton sin = Singleton.getInstance();


    // Links to FXML elements
    @FXML
    private Label counter;

    public void buttonClicked() {
        System.out.print("Click");
        sin.increment();
    }

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {

        MyTask myTask = new MyTask();
        Thread myTaskThread = new Thread(myTask);
        myTaskThread.start();
    }

    class MyTask extends Task<Void>{

        @Override
        protected Void call() throws Exception {
            while(true) {
                int count = sin.getCount();
                counter.setText(Integer.toString(count));


            }
        }

    }
}

如何让这个线程定期更新正在运行的应用程序上的FXML元素?

共有2个答案

宗政卓
2023-03-14

我相信你试图更新文本的那句话必须用在这段代码中

Platform.runLater(() -> {insert your code here});

这是更新文本值时类MyTask的外观:

class MyTask extends Task<Void>{

    @Override
    protected Void call() throws Exception {
        while(true) {
            int count = sin.getCount();
            Platform.runLater(() -> {
               counter.setText(Integer.toString(count));
            });
        }
    }

}

当试图更新用户界面上的任何内容时,您必须在应用程序线程上。上面的代码告诉程序在应用程序线程上执行代码。

邰建业
2023-03-14

您的用例不需要后台线程来完成,只需要使用javafx双向绑定和StringProperty


public class Controller implements Initializable {

  // Links to Singleton classes
  private Singleton sin = Singleton.getInstance();

  // Links to FXML elements
  @FXML
  private Label counter;

  private StringProperty singletonCounter;

  @Override
  public void initialize(URL url, ResourceBundle resourceBundle) {
    singletonCounter = new SimpleStringProperty();
    singletonCounter.set(sin.getCount() + "");
    counter.textProperty().bind(singletonCounter);
  }

  public void buttonClicked() {
    sin.increment();
    singletonCounter.setValue(sin.getCount() + "");
  }

}
 类似资料:
  • > System.out正确显示标签上的id; 第二个控制器与嵌入在第一个控制器中的FXML文件绑定。如代码所示,第二个FXML文件/控制器是动态加载的:。 当从第二个控制器中的initialize方法设置id时,id会按预期显示在标签中: public void initialize(){this.setid(“12”);} 编辑: 此窗格声明为属性 第二个:

  • 我正在尝试为用Java编写的应用程序制作GUI。 我用Scene Builder制作了fxml文档,正确设置了fx: id,现在我正在尝试对表单进行简单的更改。 我的DocumentController: 我的外汇主文件: 我现在想要的一切,都是将LabelData设置为实际时间戳,但当我运行FX主文件时,什么都不会发生。有人能帮我吗? 谢谢你保罗 更新时间: 我的整个FXML文档: 我想要的一切

  • 经过大量搜索,我发现了这样一个问题:如何创建JavaFX2.0应用程序MDI。我真正想知道的是,是否可以使用JavaFX组件和场景构建器创建一个到主窗口的弹出窗口或子窗口,以创建新窗口。 我最后给出了一个模态弹出窗口: 这是我在Scene Builder的帮助下创建的MessageBoxController类。它具有标准弹出框的基本布局,可用于显示图标(ImageView)、文本框(用于您的消息文

  • null 我是否可以从子控制器-b更改父FXML-A中标签的文本?

  • 我无法从其他类更改标签的文本。我需要不断更新主屏幕上的日期和时间,而我也可以同时执行其他功能。我使用了一个TimeSetting类,它扩展了Thread,在它的run()方法中,我使用setText()在无限循环中调用了updation命令,然后让该方法Hibernate一秒钟。但是在运行这个时,什么也没有发生,在关闭输出窗口时,我得到一个错误,说NullPointerExcpetion 下面是两

  • 我想从我用FXMLoader加载的场景中获取控制器。用例是: > 我的 JSON 管理器收到一个 JSON 对象 我启动的任务显示一个新的场景 在那之后,我有空旷的场景。 现在我这样做来填充组件 我的问题是,有没有更简单的方法来做到这一点?我有一个在 FXML 中指定的控制器 我想获得具有绑定值的实例(在本例中称为name的TextField) 提前谢谢