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=" ">
<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 值。
我猜,这就是您的代码所发生的情况。
我正在使用 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=" ">
<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)
希望有人能帮助我。
谢谢
请参阅此
If there is a fx:controller attribute on the root element, the FXMLLoader creates an instance of the specified class.
因此,如果您在代码中显式创建一个新实例,并且加载器也创建一个新实例,那么只有加载器实例会注入 fxml 值。
我猜,这就是您的代码所发生的情况。