JavaFX Обработка событий из другого класса - PullRequest
0 голосов
/ 29 сентября 2019

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

Вот моя проблема:

Для проекта я делаю приложение JavaFXэто на чистой Java без FXML. У меня есть два класса, класс контроллера Controller и класс, содержащий графические элементы GUI.

Controller имеет переменную-член типа GUI, и я пытаюсь назначить обработчик события одной из кнопок в GUI, но, похоже, он не работает. Это работает только тогда, когда я пытаюсь реализовать обработчик внутри класса GUI, но мне нужно, чтобы он работал в Comtroller.

. Конструктор Controller выглядит следующим образом:

        this.view = view;

        view.addSimpleHandler(new SimpleHandler());

view имеет тип GUI, а addSimpleHandler является функцией-членом view

SimpleHandler является внутренним классом Controller, который реализует EventHandler и переопределяет handle()функция

public void addSimpleHandler(EventHandler<ActionEvent> e) {
        simpleButton.setOnAction(e);
}

- вот мой основной метод и сигнатура класса для GUI

public class GUI extends Application {
//member variables for the GUI design including simpleButton
    private Button simpleButton;
    public static void main(String[] args) {
        GUI view = new GUI();
        Controller controller = new Controller(view);

        Application.launch(view.getClass(), args);

    }

    public GUI() {
       simpleButton = new Button("Simple button");

       //rest of code is setting up GUI into my panes
    }


    public void start(Stage primaryStage) throws Exception {
        Scene scene = new Scene(mainPane, sceneWidth, sceneHeight);
        //mainPane is a pane that contains simpleButton with a screenwidth and screenHeight
        primaryStage.setTitle("Simple");
        primaryStage.setScene(scene);
        primaryStage.show();

    }

1 Ответ

2 голосов
/ 30 сентября 2019

Не создавайте экземпляр класса приложения вручную. Чтобы понять почему, см. документацию относительно жизненного цикла JavaFX ( выделение мой):

Точкой входа для приложений JavaFX является класс Application. Среда выполнения JavaFX выполняет следующее по порядку при каждом запуске приложения:

  1. Запускает среду выполнения JavaFX, если она еще не запущена (см. Platform.startup(Runnable) для получения дополнительной информации)
  2. Создает экземпляр указанного класса приложения
  3. Вызывает метод init()
  4. Вызывает метод start(javafx.stage.Stage)
  5. Ожидает завершения приложения, что происходит, когда происходит одно из следующих действий:
    • приложение вызывает Platform.exit()
    • , последнее окно было закрыто и implicitExitатрибут Platform равен true
  6. Вызывает метод 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 требует, чтобы класс приложения имел открытый конструктор без аргументов, чтобы создать экземпляр с помощью отражения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...