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

为什么我的JavaFX标签被标记为空,尽管它在JavaFX应用程序线程中声明?

曹旭东
2023-03-14

我正在尝试创建一个时钟,它通过使用每秒都会更改的动态UI标签来监视程序的运行时。我尝试过使用下面的代码,但一直得到一个空指针异常。这个异常源于JavaFX应用程序线程上的“clock”标签,尽管它在controller类中声明过,但它似乎是空的。我还实现了这个平台。稍后运行以确保标签更新将在JavaFX线程上运行,因为标签是在该线程上声明的,但是,它仍然会引发此异常。关于为什么会发生这种情况,有什么建议吗?

控制器:

  package GUI;


import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.Timer;
import java.util.TimerTask;


public class Controller implements Initializable {
    int secondspassed = 0;
    int minutespassed = 0;
    int hourspassed = 0;
    @FXML
    private Label XPTrackerlabel;
    @FXML
    private ProgressBar XPTracker;
    @FXML
    private ComboBox Minelocation;
    @FXML
    private Label clock;


    Timer timer = new Timer();
    TimerTask ticktime = new TimerTask(){
        public void run(){
            secondspassed++;
            if (secondspassed == 60){ secondspassed = 0; minutespassed++;}
            else if (minutespassed == 60){ minutespassed = 0; hourspassed++;}
            Platform.runLater(() -> clock.setText(hourspassed + ":" + minutespassed + ":" + secondspassed));
        }
    };

    public void start() {
        timer.scheduleAtFixedRate(ticktime, 1000, 1000);
    }

    public void PressButton(ActionEvent event){
        Controller startclock = new Controller();
        startclock.start();
        System.out.println("Hello World");
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        Minelocation.getItems().addAll("North", "South", "North-East");
        XPTracker.setProgress(0.5);
        double XP = XPTracker.getProgress() * 100;
        XPTrackerlabel.setText(XP + "%");
        clock.setText(hourspassed + ":" + minutespassed + ":" + secondspassed);
    }
}

FXML文件:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>

<GridPane fx:id="UI" alignment="center" hgap="10" minHeight="300.0" minWidth="300.0" vgap="10" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="GUI.Controller">
   <columnConstraints>
      <ColumnConstraints />
      <ColumnConstraints />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
   </rowConstraints>
   <children>
      <Button fx:id="start_btn" mnemonicParsing="false" onAction="#PressButton" stylesheets="@Style.css" text="Start" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="NEVER" GridPane.rowIndex="7" GridPane.valignment="CENTER" GridPane.vgrow="NEVER" />
      <ComboBox fx:id="Minelocation" prefWidth="150.0" promptText="Select Area" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="CENTER" />
      <ProgressBar fx:id="XPTracker" prefWidth="200.0" progress="0.0" GridPane.columnIndex="1" GridPane.rowIndex="11" />
      <Label fx:id="XPTrackerlabel" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="11" GridPane.valignment="CENTER" />
      <Label fx:id="clock" GridPane.columnIndex="1" GridPane.halignment="CENTER" />
   </children>
</GridPane>

错误:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at GUI.Controller$1.lambda$run$0(Controller.java:38)
    at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
    at java.lang.Thread.run(Unknown Source)

共有1个答案

高修筠
2023-03-14

事实证明,伊泰是对的,出于某种原因,我认为在Press中创建一个新的控制器实例是个好主意,这就是为什么错误一直被抛出。只是有start()而不是创建一个新的实例,并调用start()就解决了这个问题!谢谢你的帮助。

修订后的守则如下:

软件包图形用户界面;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.Timer;
import java.util.TimerTask;


public class Controller implements Initializable {
    int secondspassed = 0;
    int minutespassed = 0;
    int hourspassed = 0;
    @FXML
    private Label XPTrackerlabel;
    @FXML
    private ProgressBar XPTracker;
    @FXML
    private ComboBox Minelocation;
    @FXML
    private Label clocker;


    Timer timer = new Timer();
    TimerTask ticktime = new TimerTask(){
        public void run(){
            secondspassed++;
            if (secondspassed == 60){ secondspassed = 0; minutespassed++;}
            else if (minutespassed == 60){ minutespassed = 0; hourspassed++;}
            Platform.runLater(() -> clocker.setText(hourspassed + ":" + minutespassed + ":" + secondspassed));
        }
    };

    public void start() {
        timer.scheduleAtFixedRate(ticktime, 1000, 1000);
    }

    public void PressButton(ActionEvent event){
        start();
        System.out.println("Hello World");
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        Minelocation.getItems().addAll("North", "South", "North-East");
        XPTracker.setProgress(0.5);
        double XP = XPTracker.getProgress() * 100;
        XPTrackerlabel.setText(XP + "%");
        clocker.setText(hourspassed + ":" + minutespassed + ":" + secondspassed);
    }
}
 类似资料:
  • 在过去的几天里,我一直在尝试JavaFX、FXML、任务和属性。我偶然发现了一种奇怪的行为,希望您能帮助我更好地理解正在发生的事情。 我有一个极简的GUI,看起来像这样:GUI 如果我单击按钮,就会创建并启动一个新任务。此任务会增加一个双属性,并且新值会写入标签并在ProgressBar中设置。任务代码可以在这里看到: FXML控制器的代码如下: 如果我运行此代码,尝试更新标签会导致以下异常:ja

  • 当我创建一个简单的非多线程JavaFX应用程序并启动它时,该应用程序会创建一些线程(JavaFXApplicationThread、JavaFXLauncher等)。这些线程中的大多数都已命名,但在我的所有JavaFX应用程序中都有一个未命名的线程(“线程-1”或“线程-2”)。我绝对不会创建自己的线程,因为我尝试启动Hello World JavaFX应用程序(由IDEA生成),其中也包含“线程

  • 是否可以使用JavaFX更改应用程序图标,还是必须使用Swing来完成?

  • 问题内容: 当用户选择在另一个线程中启动阻止进程的菜单项时,我试图在JavaFX 8应用程序中提供反馈。在我的实际应用程序中,它是文件下载,但是通过示例,我使用最少的代码创建了一个测试用例: 它的工作方式如下:当选择“开始”菜单项时,主菜单文本应立即更改为“正在运行…”,然后应附加“完成!”。经过5秒钟的模拟我的文件下载的睡眠。 实际上发生的是,即使我正在使用,在阻止过程完成 后 , 两个 文本更

  • 问题内容: 我在TableView中添加了默认的TEST1和TEST2作为Name Col,但是在运行它时却没有显示。这是我使用过的两个类和一个fxml,有人可以给我一些有关此问题的建议吗? 仅一个包调用:controllerJBoxFXTest 第一类MainView.class包controllerJBoxFXTest; 在第二个MainController.java中,可以看到我添加了TES

  • 这是:“Parent root=fxmlloader.load(getClass().getResource(”sample.fxml“));” 我不明白剩下的部分,所以我希望你能轻松地解决这个问题:)