Не создавайте экземпляр класса приложения вручную. Чтобы понять почему, см. документацию относительно жизненного цикла JavaFX ( выделение мой):
Точкой входа для приложений JavaFX является класс Application. Среда выполнения JavaFX выполняет следующее по порядку при каждом запуске приложения:
- Запускает среду выполнения JavaFX, если она еще не запущена (см.
Platform.startup(Runnable)
для получения дополнительной информации) - Создает экземпляр указанного класса приложения
- Вызывает метод
init()
- Вызывает метод
start(javafx.stage.Stage)
- Ожидает завершения приложения, что происходит, когда происходит одно из следующих действий:
- приложение вызывает
Platform.exit()
- , последнее окно было закрыто и
implicitExit
атрибут Platform
равен true
- Вызывает метод
stop()
Как видите, сама JavaFX будет создавать экземпляр класса приложения иэто тот экземпляр , для которого были вызваны методы его жизненного цикла - это методы init()
, start(Stage)
и stop()
. Однако в вашем коде есть следующее:
public static void main(String[] args) {
GUI view = new GUI(); // created your own instance
Controller controller = new Controller(view); // gave controller that instance
// Launches JavaFX which starts the life-cycle documented above
Application.launch(view.getClass(), args);
}
Вы создаете свой собственный экземпляр GUI
. Этот экземпляр не управляется JavaFX, что означает, что его метод start(Stage)
никогда не вызывается. Когда вы создаете экземпляр Controller
и передаете его своему экземпляру GUI
, вы добавляете EventHandler
к узлу, который никогда не отображается. Отображаемое окно открывается из экземпляра GUI
, созданного как часть вызова Application#launch
, и этот экземпляр GUI
никогда не ассоциируется с Controller
.
Для приложений JavaFX следует учитыватьМетоды init()
и start(Stage)
в качестве точек входа 1 . Другими словами, создайте Controller
в одном из вышеупомянутых методов жизненного цикла. Хотя я полагаю, вы могли бы сделать то же самое в конструкторе вместо 2 . Независимо от того, что вы выберете, запомните, какой поток вызывает каждый метод, который задокументирован в том же месте, что и жизненный цикл . Вот основные сведения:
- Класс приложения загружается, инициализируется и создается в потоке приложений JavaFX .
- Метод
init()
вызывается JavaFX-Launcher thread. - Методы
start(Stage)
и stop()
вызываются Потоком приложения JavaFX .
Помните, что некоторые действия могут выполняться только в потоке приложений JavaFX .
1. Вы все еще можете выполнить код перед вызовом Application#launch
в методе main, если это необходимо. Единственным ограничением является то, что код не должен быть напрямую связан с JavaFX.
2. Ваш конструктор в настоящее время общедоступен и имеет нулевые параметры - оставьте это так. JavaFX требует, чтобы класс приложения имел открытый конструктор без аргументов, чтобы создать экземпляр с помощью отражения.