label.setText NullPointerException

Привет, первый раз здесь, но вот:

У меня есть приложение JavaFX, которое динамически изменяет метки пользовательского интерфейса FXML, а данные извлекаются из класса Player.

Речь идет о двух классах Player.java и InterfaceHandler.java.

Класс игрока хранит сведения об игроке, и я хочу передать эти сведения классу интерфейса, который устанавливает текст на метках.

В качестве теста мой пользовательский интерфейс FXML имеет только кнопку и две метки.

Если он нажмет кнопку, он вызовет метод handleButton, он установит locationLabel в «Город» в порядке.

Однако, если я вызываю метод locationLabel() в своем классе Player, я получаю исключение NullPointerException при вызове nameLabel.setText(name). В ходе отладки я обнаружил, что строка имени в классе интерфейса — это то, что должно быть «Дэн».

Кто-нибудь может помочь?

Основной класс:

public class Main extends Application {

    public void start(final Stage mainStage) throws Exception {

        Parent root = FXMLLoader.load(getClass().getResource("MainScreen.fxml"));
        Scene scene = new Scene(root);
        mainStage.setTitle("Main Screen");
        mainStage.setScene(scene);
        mainStage.show();    
    }

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

Класс игрока:

public class Player{

InterfaceHandler ui = new InterfaceHandler();   

 public void setNameLabel() {

    String name = "Dan";
    ui.setName(name);
}

Класс InterfaceHandler:

    public class InterfaceHandler implements Initializable {

       public Label nameLabel;
       public Label locationLabel;    

public void handleButton(ActionEvent event) throws IOException {        

        locationLabel.setText("Town");
    }

public void setName(String name){       
        nameLabel.setText(name);
    }    
}

MainScreen.fxml:

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

    <?import java.lang.*?>
    <?import java.net.*?>
    <?import java.util.*?>
    <?import javafx.scene.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.effect.*?>
    <?import javafx.scene.image.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.scene.text.*?>

    <AnchorPane id="AnchorPane" prefHeight="629.0" prefWidth="600.0" snapToPixel="true" style="-fx-background-color:  beige;" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="application.InterfaceHandler">
      <children>            
        <Button fx:id="button1" layoutX="512.0" layoutY="381.0" minWidth="14.0" mnemonicParsing="false" onAction="#handleButton" prefHeight="30.0" prefWidth="51.0" text="Town" visible="true" />        

        <Label fx:id="nameLabel" layoutX="57.0" layoutY="8.0" prefWidth="216.0" text="blank" />
        <Label fx:id="locationLabel" layoutX="68.0" layoutY="27.0" prefWidth="193.0" text="blank" />
      </children>
    </AnchorPane>

person twin_suns    schedule 20.03.2014    source источник


Ответы (2)


Это потому, что вы неправильно вставили свой Labels из файла FXML.

Аннотируйте свои Label vars. с аннотацией FXML:

public class InterfaceHandler implements Initializable {
    @FXML
    public Label nameLabel;
    @FXML
    public Label locationLabel;    

    public void handleButton(ActionEvent event) throws IOException {        
        locationLabel.setText("Town");
    }

    public void setName(String name){       
        nameLabel.setText(name);
    }    
}

Кроме того, InterfaceHandler — это контроллер, на который вы ссылаетесь с помощью fx:controller в вашем FXML. Это указывает FXMLLoader создать новый экземпляр InterfaceHandler, когда загрузчик загружает свой FXML. Поэтому не создавайте новый InterfaceHandler в своем классе Player, вместо этого сделайте InterfaceHandler параметром конструктора для Player и используйте loader.getController, чтобы получить экземпляр контроллера InterfaceHandler из FXMLLoader.

FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("MainScreen.fxml"));
Parent root = (Parent)loader.load();
Player player = new Player(loader.getController());
Scene scene = new Scene(root);

. . .

public class Player {
  private InterfaceHandler ui;   

  public Player(InterfaceHandler ui) {
    this.ui = ui;
  }

  public void setNameLabel() {
    String name = "Dan";
    ui.setName(name);
  }
}
person Branislav Lazic    schedule 20.03.2014
comment
Спасибо, это сработало! Однако мне пришлось добавить актерский состав, чтобы все заработало: Player player = new Player((InterfaceHandler) loader.getController()); - person twin_suns; 21.03.2014
comment
Если вы используете NetBeans, используйте параметр make controller, чтобы создать файлы контроллера из fxml. Он сделает инъекцию FXML за вас. - person Sudip Saha; 22.03.2014

У меня была похожая проблема, но оказалось, что я сделал метку статическим атрибутом, и когда я удалил статическую часть, это исправило исключение нулевого указателя.

person Yash Kalia    schedule 17.12.2019