为什么当字段声明为 super-type 时 FXMLLoader 不初始化字段
Why does FXMLLoader not initialize fields when a field is declared as a super-type
当我如下图声明一个野外玩家时:
class Controller{
@FXML Shape player;
}
.fxml 文件 - <Rectangle fx:id="player" ...\>
在 Controller
中,player
被声明为超类型 (Shape
),而在 fxml 文件中
它被声明为子类型。
我将播放器声明为 Shape
,而不是 Rectangle
,因为我有多个类似的 fxml 文件,程序会在运行时决定加载哪一个。每个 fxml 文件都有一个播放器 object 的 child class 的 Shape
我的问题是,当一个字段声明为超类型时,fxml 加载程序不会初始化该字段。我想知道 work-around 这个问题。
一个最小可重现的例子:
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
-注解字段在控制器中初始化。通常要创建控制器,您需要在 FXML 的根元素中指定一个 fx:controller
属性(尽管还有其他方法可以做到这一点)。您的 test2
class [原文如此] 不是控制器 class(即使是,调用 start()
的实例也不是控制器)。
您的代码的以下修改表明声明为 superclass 类型的字段确实如您所期望的那样被初始化:
Controller.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>
Test2.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]
当我如下图声明一个野外玩家时:
class Controller{
@FXML Shape player;
}
.fxml 文件 - <Rectangle fx:id="player" ...\>
在 Controller
中,player
被声明为超类型 (Shape
),而在 fxml 文件中
它被声明为子类型。
我将播放器声明为 Shape
,而不是 Rectangle
,因为我有多个类似的 fxml 文件,程序会在运行时决定加载哪一个。每个 fxml 文件都有一个播放器 object 的 child class 的 Shape
我的问题是,当一个字段声明为超类型时,fxml 加载程序不会初始化该字段。我想知道 work-around 这个问题。
一个最小可重现的例子:
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
-注解字段在控制器中初始化。通常要创建控制器,您需要在 FXML 的根元素中指定一个 fx:controller
属性(尽管还有其他方法可以做到这一点)。您的 test2
class [原文如此] 不是控制器 class(即使是,调用 start()
的实例也不是控制器)。
您的代码的以下修改表明声明为 superclass 类型的字段确实如您所期望的那样被初始化:
Controller.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>
Test2.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]