When I declare a field player as shown below:
class Controller{
@FXML Shape player;
}
.fxml file - <Rectangle fx:id="player" ...\>
Where in the Controller
, player
is declared as a super type (Shape
), and in the fxml file
it is declared as a subtype.
I declare player as Shape
, instead of Rectangle
, because I have multiple similar fxml files, and the program decides, during runtime, which one to load. Every fxml file has a player object of some child class of Shape
My problem is that when a field is declared as the super type, fxml loader doesn't initialize that field. I would like to know a work-around to this problem.
A minimum reproducible example:
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
-annotated fields are initialized in the controller. Typically to create controllers, you specify a fx:controller
attribute in the root element of the FXML (though there are other ways to do this). Your test2
class [sic] is not the controller class (and even if it were, the instance on which start()
is invoked would not be the controller).
The following modification of your code demonstrates that fields declared as a superclass type are indeed initialized as you would expect:
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 (note fx:controller
attribute):
<?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);
}
}
This generates the expected output:
Rectangle[id=player, x=20.0, y=20.0, width=40.0, height=40.0, fill=0x000000ff]