2016-01-04 5 views
0

Я создаю небольшую программу в JavaFX и имею кнопку, которую мне нужно назначить EventHandler. Я создаю и назначаю эту кнопку в методе init() класса View (класс, который расширяет Application).Метод инициализации JavaFX init() в значение null

Button ok = new Button(" OK "); 
ok.setOnAction(this.eventHandler); 

В идеале я хотел бы передать эту EventHandler в том, когда я построить вид объекта, но у меня были некоторые трудности делают это, так я решил сам просто используя простой метод установки.

public void setEventHandler(EventHandler<ActionEvent> eventHandler) { 
this.eventHandler = eventHandler; 
} 

Чтобы начать все с, я бегу несколько строк кода в основной метод моего класса контроллера:

View v = new View(); 
v.setEventHandler(new HandleOk(v)); 
javafx.application.Application.launch(View.class); 

Где HandleOk находится в EventHandler. Ему нужна ссылка на мой класс представления, чтобы он мог запрашивать состояние некоторых своих полей и, таким образом, был создан с помощью представления. Выполнение этого кода и нажатие на кнопку JavaFX приводит к исключению нулевого указателя.

Затем я установил три System.out.format("Event handler is null: %b\n", v.eventHandler == null);, один из которых в моем основном методе контроллера, один в верхней части моего метода init() моего представления (метод, унаследованный от приложения JavaFX) и в методе setOnAction кнопки. Таким образом, следующее:

public class Controller { 
    //~~ other stuff ~~ 
    public static void main(String[] args) { 
    View v = new View(); 
    v.setEventHandler(new HandleOk(v)); 
    System.out.format("Event handler is null: %b\n", v.eventHandler == null); 
    javafx.application.Application.launch(View.class); 
    } 
//~~ other stuff ~~ 
} 

public class View extends Application { 
    EventHandler<ActionEvent> eventHandler; 

    public void setEventHandler(EventHandler<ActionEvent> eventHandler) { 
    System.out.println("Event Handler set"); 
    this.eventHandler = eventHandler; 
    } 

    @Override 
    public void init() { 
    System.out.format("Event Handler in init() is null: %b\n", eventHandler == null); 
    // ~~ other stuff ~~ 
    Button ok = new Button(" OK "); 
    ok.setOnAction((ActionEvent) -> { 
     System.out.format("Event Handler in button is null: %b", this.eventHandler == null)); 
     if (!(this.eventHandler == null) { 
     this.eventHandler.handle(ActionEvent); 
     } 
    }); 
// ~~ other stuff ~~ 
    } 

Запуск этого и нажав на кнопку в моем приложении JavaFX приводит к следующему печатается на консоль:

Event Handler set 
Event Handler is null: false 
Event Handler in init() is null: true 
Event Handler in button is null: true 

Интересно, добавив следующую строку в моей инициализации () удаляет исключение нулевого указателя, и мое приложение работает.

public void init() { 
    eventHandler = new Controller.HandleOk(this); 
// ~~ other stuff ~~ 
} 

В идеале я хотел бы мой контроллер, чтобы передать в HandleOk на мой взгляд, и не мой взгляд, чтобы захватить HandleOk от моего контроллера. Я могу только заключить, что когда JavaFX загружает класс, расширяющий приложение, он сбрасывает все инициализированные поля, что приводит к ситуации, когда вы можете инициализировать поля только в методе init(). Как я могу передать HandleOk в представление из внешнего источника?

+0

Не "javafx.application.Application.launch (View.class);" создать собственный экземпляр View? Это означало бы все, что вы делали до того, как это будет бессмысленно, поскольку экземпляр, который отображается, не является созданным вами экземпляром. – MadProgrammer

+0

Документация подтверждает ваш ответ, поэтому теперь я знаю, почему поле, похоже, сбрасывается. Запуск - это метод void и, однако, не возвращает ссылку на экземпляр, поэтому я все еще теряюсь в том, как проходить в HandleOk извне. –

ответ

1

The

Application.launch(View.class) 

создает новый экземпляр View, где он имеет нулевое значение для обработчика событий по умолчанию, а также отличается от класса View вы создали сами. Также, если вы заметили, что метод init() класса View вызывается только один раз. Это вызвано методом Application.launch.

Предлагаю разделить логику вида и приложения на разные классы. То есть не расширяйте представление от Application, создайте еще один класс MainApp, который расширяет приложение.

+0

Можете ли вы подробно остановиться на логике просмотра и приложения? Моя мысль заключалась в том, что у моего представления есть кнопка, которая при нажатии будет выводить мой контроллер. Оттуда мой Контролер разговаривает с моей Моделью, чтобы выполнить эту работу. Как бы этот поток выглядел по-другому, разделив мой вид и приложение? –

+0

В основном мой контроллер должен быть классом, который расширяет приложение, поскольку он является точкой входа для моей программы. Понял. –

0

Вы установили Поле?

public void setEventHandler(EventHandler<ActionEvent> eventHandler) { 
    System.out.println("Event Handler set"); 
    this.eventHandler = eventHandler; // missing? 
} 
+0

Упс, опечатка.Да. Будет редактировать это. –

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