Inyección @FXML de componente personalizado hace variable no instantiate en el controlador y conduce a NullPointerException

user3182445:

He creado un componente personalizado llamado PlayerViewque tiene un asociado PlayerView.fxml diseño FXML y PlayerView.java clase para crear una instancia del componente. A continuación, incluyo varias instancias de este componente en otro FXML Layout llamados Board.fxml e intento para referirse a estos casos en el controlador del Consejo Board.java mediante el uso de la @FXMLanotación para crear una inyección. Sin embargo, esta inyección no funciona como se pretende desde consigo una NullPointerExceptioncuando intento hacer referencia a PlayerViewcasos en mi controlador.

PlayerView.fxml

<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
    ...
</fx:root>

PlayerView.java

public class PlayerView extends VBox {
    public PlayerView() {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("PlayerView.fxml"));
        loader.setRoot(this);
        loader.setController(this);
        try {
            loader.load();
        } catch (IOException e) { 
            e.printStackTrace();
        }
    }
    public void init(String name) {
        ...
    }
}

Board.fxml

<VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
      fx:controller="pablo.Board" prefHeight="400.0" prefWidth="600.0" alignment="CENTER">
    <BorderPane>
        <top>
            <PlayerView BorderPane.alignment="TOP_CENTER" fx:id="playerView2"/>
        </top>
        <bottom>
            <PlayerView BorderPane.alignment="BOTTOM_CENTER" fx:id="playerView1"/>
        </bottom>
        <left>
            <PlayerView BorderPane.alignment="CENTER_LEFT" fx:id="playerView3"/>
        </left>
        <right>
            <PlayerView BorderPane.alignment="CENTER_RIGHT" fx:id="playerView4"/>
        </right>
        ...
    </BorderPane>
    ...
</VBox>

Board.java

public class Board extends Application {
    ...
    @FXML PlayerView playerView1, playerView2, playerView3, playerView4;
    @Override
    public void start(Stage primaryStage) throws IOException, ClassNotFoundException {
        Parent root = FXMLLoader.load(getClass().getResource("Board.fxml"));
        Scene scene = new Scene(root);
        primaryStage.setTitle("Pablo!");
        primaryStage.setScene(scene);
        primaryStage.show();

        playerViews = new PlayerView[]{ playerView1, playerView2, playerView3, playerView4 };
        playerView1.init(playerName); // NullPointerException occurs at this line
        ...
    }
}

Seguimiento de la pila

Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$1(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
    at pablo.Board.start(Board.java:39)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

¿Hay algo mal con la forma en que estoy usando la @FXMLanotación en Board.java para referirse a mis PlayerViewcasos en Board.fxml ? ¿Cómo debo referiré a ellos en su lugar?

c0der:

definir PlayerView:

PlayerView.fxml

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

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml"> 
    <Label fx:id="nameLbl" alignment="CENTER" contentDisplay="CENTER" prefHeight="66.0" prefWidth="87.0" text="--" />
</fx:root>

PlayerView.java que también sirve como controlador:

public class PlayerView extends VBox {

    @FXML Label nameLbl;

    public PlayerView() {

        FXMLLoader loader = new FXMLLoader(getClass().getResource("PlayerView.fxml"));
        loader.setRoot(this);
        loader.setController(this);

        try {
            loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void init(String name) {
        nameLbl.setText(name);
    }
}

Board.fxml y su controlador:

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

<?import fx_tests.a_test.PlayerView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>

<VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" prefHeight="400.0" 
prefWidth="600.0" alignment="CENTER" fx:controller="foo.bar.BoardController">
    <BorderPane>
        <top>
            <PlayerView  fx:id="playerView2"/>
        </top>
        <bottom>
            <PlayerView  fx:id="playerView1"/>
        </bottom>
        <left>
            <PlayerView  fx:id="playerView3"/>
        </left>
        <right>
            <PlayerView fx:id="playerView4"/>
        </right>
    </BorderPane>
</VBox>

Dejar que el cambio de controlador de Boaedestado según sea necesario:

public class BoardController{

    @FXML PlayerView playerView1, playerView2, playerView3, playerView4;

    public PlayerView getBottom(){
        return playerView1;
    }

    public PlayerView getTop(){
        return playerView2;
    }

    public PlayerView getLeft(){
        return playerView3;
    }

    public PlayerView getRight(){
        return playerView4;
    }
}

Obtener el controlador en Boardy utilizarlo:

public class Board extends Application {

    @FXML PlayerView playerView1, playerView2, playerView3, playerView4;
    @Override
    public void start(Stage primaryStage) throws IOException, ClassNotFoundException {

        FXMLLoader loader = new FXMLLoader(getClass().getResource("Board.fxml"));
        VBox root = loader.load();
        BoardController controller = loader.getController();

        Button btn = new Button("Add Names");
        btn.setOnAction(e->{
            controller.getTop().init("Top");
            controller.getBottom().init("Bottom");
            controller.getLeft().init("Left");
            controller.getRight().init("Right");
        });
        root.getChildren().add(btn);
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(null);
    }
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=367381&siteId=1
Recomendado
Clasificación