JavaFX - окно FileChooser открывается, но начальная модальность по умолчанию не работает

Я создал приложение, в котором мне нужно щелкнуть элемент меню «Открыть ...», чтобы открыть FileChooser. FileChooser открывается, но проблема в том, что я могу щелкнуть или закрыть первое окно, пока этот FileChooser все еще открыт.

У меня проблема в моем коде? Неправильно ли указывать primaryStage в качестве параметра для fileChooser.showOpenDialog(primaryStage); ?

Это мои декларации

private Stage primaryStage;

Это мой метод запуска.

@Override
public void start(Stage primaryStage) {
    this.primaryStage = primaryStage;
    primaryStage.setTitle("Ontology - Language Disorders");
    primaryStage.centerOnScreen();
    initRootLayout();
    showOntologyOverview();
    primaryStage.show();
}

Это мой OpenDialog

@FXML
private void handleOpenMenuItem(ActionEvent event){
    FileChooser fileChooser = new FileChooser();
    fileChooser.setTitle("Open Resource File");
    fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("OWL (*.owl)", "*.owl"));
    fileChooser.showOpenDialog(primaryStage);
}

Мой initRootLayout:

public void initRootLayout() {
    try {
        // Load root layout from fxml file.
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(MainApp.class.getResource("RootLayout.fxml"));
        rootLayout = (BorderPane) loader.load();
        // Show the scene containing the root layout.
        Scene scene = new Scene(rootLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

person Mohamed Benmahdjoub    schedule 08.04.2015    source источник
comment
Это не то, что происходит ._. я действительно не знаю почему, я все еще могу выполнять любые действия, например закрывать главное окно :(   -  person Mohamed Benmahdjoub    schedule 08.04.2015
comment
Я смущен. Это ваш подкласс Application или класс вашего контроллера?   -  person James_D    schedule 08.04.2015
comment
я использовал один и тот же класс для обоих, я имею в виду, что основное приложение имеет эти методы.   -  person Mohamed Benmahdjoub    schedule 08.04.2015
comment
Тот же класс, но у вас разные экземпляры этого класса. Где вы инициализируете primaryStage в экземпляре контроллера? (Кстати, это вообще ужасная идея; она слишком запутана, поскольку почти невозможно отследить, какие вещи были инициализированы и какие методы были вызваны.)   -  person James_D    schedule 08.04.2015
comment
Я запутался в вопросе и поэтому удалил свой комментарий. У вас есть multiple stages, пока вы открываете FileChooser?   -  person ItachiUchiha    schedule 08.04.2015
comment
james_D я добавил initRootLayout   -  person Mohamed Benmahdjoub    schedule 08.04.2015
comment
Пожалуйста, добавьте весь код в качестве правок к вопросу.   -  person ItachiUchiha    schedule 08.04.2015
comment
ИтачиУчиха, да, у меня есть элемент меню «Открыть».   -  person Mohamed Benmahdjoub    schedule 08.04.2015
comment
Добавлен код методов!   -  person Mohamed Benmahdjoub    schedule 08.04.2015
comment
Нет необходимости вызывать primaryStage.show() внутри start() и initRootLayout(). Просто позвоните из одного места. Код не имеет никакого смысла в том, почему ваш код не работает должным образом. Можете ли вы создать MCVE и опубликовать его?   -  person ItachiUchiha    schedule 08.04.2015
comment
Ok ! Спасибо ! я буду стараться   -  person Mohamed Benmahdjoub    schedule 08.04.2015


Ответы (1)


Вы используете класс Application в качестве класса контроллера для вашего FXML. Это очень сбивает с толку, и вам следует избегать этого.

Вот что происходит:

  1. Вы запускаете приложение. Это вызывает инициализацию инструментария FX, запуск потока приложения FX, создание экземпляра вашего подкласса Application, создание Stage и вызов start(...) в этом экземпляре в потоке приложения FX.
  2. Ваш метод start устанавливает поле primaryStage экземпляра, созданного последовательностью запуска.
  3. Вы создаете FXMLLoader и загружаете файл FXML.
  4. FXMLLoader создает экземпляр класса контроллера (который оказывается подклассом Application). Затем он инициализирует все поля с аннотациями @FXML в этом экземпляре и регистрирует методы обработчика. Обратите внимание, что поле primaryStage никогда не инициализируется в этом экземпляре.

Когда пользователь нажимает «Открыть» MenuItem, метод handleOpenMenuItem() вызывается для экземпляра, созданного на шаге 4 (а не для экземпляра, созданного на шаге 1). Вы создаете FileChooser и вызываете showOpenDialog(...), передавая значение primaryStage. Поскольку в данном случае primaryStage равно null, средство выбора файлов не имеет окна владельца и поэтому не может реализовать какую-либо значимую модальность.

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

person James_D    schedule 08.04.2015
comment
Ok ! я попробую это, большое спасибо! - person Mohamed Benmahdjoub; 08.04.2015
comment
ДАААААААА! проблема была в инициализации :D спасибо вам обоим! :D - person Mohamed Benmahdjoub; 08.04.2015