java - 为什么当字段声明为超类型时,FXMLLoader 不初始化字段
问题描述
当我声明一个外场球员时,如下所示:
class Controller{
@FXML Shape player;
}
.fxml 文件 -<Rectangle fx:id="player" ...\>
其中Controller
,player
被声明为超类型 ( Shape
),在 fxml 文件中它被声明为子类型。
我将 player 声明为Shape
,而不是Rectangle
,因为我有多个类似的 fxml 文件,并且程序在运行时决定加载哪个文件。每个 fxml 文件都有一个子类的播放器对象Shape
我的问题是,当一个字段被声明为超类型时,fxml 加载器不会初始化该字段。我想知道这个问题的解决方法。
一个最小可重现的例子:
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
public class test2 extends Application {
@FXML Shape player;
public void start(Stage stage) throws Exception
{
Scene scene = new Scene(
FXMLLoader.load(getClass().getResource("t.fxml"))
);
stage.setTitle("JavaFX Example");
stage.setScene(scene);
stage.show();
System.out.println(player); //prints null
}
public static void main (String [] args){
launch(args);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.shape.Rectangle?>
<Pane xmlns:fx="http://javafx.com/fxml" prefHeight="400.0" prefWidth="600.0">
<Rectangle fx:id="player" x="20" y="20" width="40" height="40"/>
</Pane>
解决方案
@FXML
-注释字段在控制器中初始化。通常要创建控制器,您需要fx:controller
在 FXML 的根元素中指定一个属性(尽管还有其他方法可以做到这一点)。您的test2
类 [sic] 不是控制器类(即使是,start()
调用的实例也不是控制器)。
您的代码的以下修改表明声明为超类类型的字段确实按照您的预期进行了初始化:
控制器.java:
package org.jamesd.examples.supertype;
import javafx.fxml.FXML;
import javafx.scene.shape.Shape;
public class Controller{
@FXML Shape player;
public void initialize() {
System.out.println(player);
}
}
t.fxml(注释fx:controller
属性):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.shape.Rectangle?>
<Pane xmlns:fx="http://javafx.com/fxml" prefHeight="400.0"
prefWidth="600.0"
fx:controller="org.jamesd.examples.supertype.Controller">
<Rectangle fx:id="player" x="20" y="20" width="40" height="40" />
</Pane>
测试2.java:
package org.jamesd.examples.supertype;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
public class Test2 extends Application {
@FXML Shape player;
public void start(Stage stage) throws Exception
{
Scene scene = new Scene(
FXMLLoader.load(getClass().getResource("t.fxml"))
);
stage.setTitle("JavaFX Example");
stage.setScene(scene);
stage.show();
}
public static void main (String [] args){
launch(args);
}
}
这会生成预期的输出:
Rectangle[id=player, x=20.0, y=20.0, width=40.0, height=40.0, fill=0x000000ff]
推荐阅读
- linux-kernel - 我们可以为 U-boot(Raspberry pi 4B)从旧版“图像”生成 FIT 图像吗?
- javascript - 用户注销时如何路由到另一个网站 - Angular
- android - Android - 从 BroadcastReceiver 启动关闭的应用程序
- java - 如何从 Java 中的泛型类型中获取方法?
- c# - C#,使用 Directory.GetFiles 读取字符串数组的每一行
- reactjs - 使用 Firebase 快照对异步操作进行 React useEffect 链接
- python - 解压过滤器对象
- migration - 如何在 TYPO3 v10 中访问 $GLOBALS['TSFE']
- java - 如何确定来自 POI 的 `OpenException` 是否与 Zip Bomb 相关而不是其他打开问题
- css - 模态打开时防止滚动