JavaFX 意外的 NullPointerException

JavaFX Unexpected NullPointerException

我正在使用 JavaFX 和 MVC 架构开发一个游戏项目

这是我的一个观点

package fr.arnoux23u.javano.mvc.views;

import fr.arnoux23u.javano.mvc.*;
import javafx.fxml.*;
import javafx.scene.control.TextArea;

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

/**
 * @author arnoux23u
 */
public class ServerView implements Initializable, Observer {

    @FXML
    private TextArea clientsList;

    @Override
    public synchronized void update(Model m) {
        System.out.println("[UPDATE] "+Thread.currentThread().getName());
        clientsList.setText("test");
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        System.out.println("[INITIALIZE] "+Thread.currentThread().getName());
        clientsList.setText("Aucun joueur ici");
    }
}

还有我的 FXML 文件

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>

<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.arnoux23u.javano.mvc.views.ServerView">
    <Label text="JavaNo - Server">
        <font>
          <Font size="23.0" />
        </font>
    </Label>
    <Label alignment="CENTER" text="Connected Clients">
        <font>
          <Font size="23.0" />
        </font>
    </Label>
    <TextArea fx:id="clientsList" editable="false" maxWidth="200.0" prefHeight="200.0" prefWidth="200.0" style="-fx-focus-color: -fx-control-inner-background;" text="&#10;&#10;">
      <VBox.margin>
         <Insets top="20.0" />
      </VBox.margin>
      <font>
         <Font size="18.0" />
      </font></TextArea>
</VBox>

当我加载应用程序时,TextArea clientsList 的文本被正确设置为“Aucun joueur ici”,但是当我想更新文本(使用 MVC)时,我在 clientsList

上有一个 NullPointerException

首先,我认为这是一个线程错误,因为运行 update 方法的线程不是“JavaFX 应用程序线程”

所以在我的 MVC 控制器中,我使用 Platform.runlater() 方法。

@Override
    public void notifyObservers() {
        observers.forEach(o -> {
            System.out.println("[FOREACH] "+Thread.currentThread().getName());
            Platform.runLater(() -> {
                System.out.println("[PLATFORM] "+Thread.currentThread().getName());
                o.update(this);
            });
        });
    }

我调用更新时的输出是

[INITIALIZE] JavaFX Application Thread
[FOREACH] Thread-3
[PLATFORM] JavaFX Application Thread
[UPDATE] JavaFX Application Thread

但即使使用 runLater 方法,我也有 NullPointerException

这是完整的堆栈跟踪

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "javafx.scene.control.TextArea.setText(String)" because "this.clientsList" is null
    at fr.arnoux23u.javano/fr.arnoux23u.javano.mvc.views.ServerView.update(ServerView.java:34)
    at fr.arnoux23u.javano/fr.arnoux23u.javano.mvc.Game.lambda$notifyObservers(Game.java:54)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:457)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:456)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop(WinApplication.java:184)
    at java.base/java.lang.Thread.run(Thread.java:833)

希望有人能帮助我。

谢谢

请参阅此 的第 3 步:

If there is a fx:controller attribute on the root element, the FXMLLoader creates an instance of the specified class.

因此,如果您在代码中显式创建一个新实例,并且加载器也创建一个新实例,那么只有加载器实例会注入 fxml 值。

我猜,这就是您的代码所发生的情况。