2016-03-23 2 views
0

я имею следующую проблему с программой, что я в настоящее время пишу, и я искал в Интернете, но я не мог найти что-нибудь, чтобы помочь мне понять следующую проблемуJavaFX, Лейбл пустой указатель исключение

Так внутри другого класса я написал метод, который выполняет это каждый раз, когда кнопка поиска нажата и метод выглядит следующим образом:

public void searchButton(){ 
     try { 
      new SearchController().display(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

и тогда класс SearchController выглядит примерно так (я упростил его здесь):

public class SearchController { 

    @FXML 
    private Button cancelButton; 

    @FXML 
    private Label what; 

    private static Stage stage; 

    private static BorderPane borderPane; 

    @FXML 
    public void initialize(){ 
     what.setText("Testing"); // this woks 
     cancelButton.setOnAction(e -> stage.close()); 
    } 

    public void display() throws IOException { 

     stage = new Stage(); 
     stage.setResizable(false); 
     stage.setTitle("Product search"); 
     stage.initModality(Modality.APPLICATION_MODAL); 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(SearchController.class.getResource("Search.fxml")); 
     borderPane = loader.load(); 
     Scene scene = new Scene(borderPane); 
     stage.setScene(scene); 
     //what.setText("Testing") and this doesn't work 
     stage.showAndWait(); 

    } 



} 

Может кто-нибудь, пожалуйста, скажите мне, почему можно написать текст по методу initialize (этот метод вызывается после строки borderPane = loader.load(); ... так почему это не работает, если я пытаюсь написать на ярлыке после этой строки ?)

Спасибо заранее

+0

В качестве примечания обратите внимание, что ваши «статические» поля будут катастрофой, если вы в конечном итоге загрузите файл FXML дважды (и одновременно отобразите оба изображения). Вам это совсем не нужно, и они ждут ошибок. Вы можете использовать 'cancelButton.setOnAction (e -> cancelButton.getScene(). GetWindow(). Hide());' закрыть окно (и избавиться от поля 'stage'. Если вам действительно нужна' borderPane', поле, сделайте его переменной экземпляра и введите его из файла fxml (т. е. удалите 'static' и просто поместите' fx: id = "borderPane" на корневой элемент fxml). –

ответ

2

The FXMLLoader создает экземпляр класса, указанного в атрибуте FXML корневого элемента fx:controller. Затем он вводит элементы, определенные в файле FXML, в экземпляр контроллера , он создал, когда атрибуты fx:id соответствуют именам полей. Затем он вызывает метод initialize() в этом экземпляре.

Вы создаете экземпляр контроллера «вручную» с помощью new SearchController(). Это не тот объект, который создается FXMLLoader. Итак, теперь, когда вы загрузили файл fxml, у вас есть два разных экземпляра SearchController. Поэтому, если вы вызываете what.setText(...) из метода display(), вы не вызываете его на экземпляр контроллера, созданный FXMLLoader. Следовательно, what не был инициализирован в экземпляре, на котором вы вызываете what.setText(...), и вы получаете исключение с помощью null-указателя.

С initialize() вызывается FXMLLoader на экземпляре он создал, когда вы звоните what.setText(...) от метода initialize(), вы вызываете его на экземпляр, созданный FXMLLoader, и поэтому FXML впрыском поля для этого экземпляра были инициализируется.

+0

Спасибо за объяснение, у меня есть только что начал JavaFX, так что пока это еще не ясно. Что было бы хорошим способом открыть новое окно? Не только в этом случае вообще? Потому что до сих пор я думал, что должен сделать это, создав новый объект из класса контроллера. – TimNeutron

+0

Используя настройку по умолчанию, «FXMLLoader» создает контроллер из файла fxml, поэтому в этой настройке вы никогда не должны создавать объекты контроллера самостоятельно. Код, который вы используете в методе 'display()' точно код, необходимый для создания нового окна и отображения содержимого файла fxml в нем, но это просто не т ake смысл сделать этот метод экземпляра в классе контроллера; вы обычно просто имеете этот код в точке вашего приложения, где вам нужно было создать окно. –

+0

О, я вижу. Еще раз спасибо, похоже, я неправильно понял концепцию. Еще один быстрый вопрос: Это: 'SearchController a = loader.getController()' не создает права на новый экземпляр?Я думаю, что я получил концепцию сейчас, благодаря вам: D – TimNeutron

Смежные вопросы