Как открыть JavaFX FileChooser из класса контроллера?

Моя проблема в том, что все примеры использования FileChooser требуют прохождения этапа. Единственная проблема заключается в том, что мой пользовательский интерфейс определен в файле fxml, в котором используется класс контроллера, отдельный от основной сцены.

@FXML protected void locateFile(ActionEvent event) {
    FileChooser chooser = new FileChooser();
    chooser.setTitle("Open File");
    chooser.showOpenDialog(???);
}

Что мне поставить на ???, чтобы он заработал? Как я уже сказал, у меня нет никаких ссылок ни на какие этапы в классе контроллера, так что же мне делать?


person Electric Coffee    schedule 25.08.2014    source источник


Ответы (4)


Для любого узла в вашей сцене (например, корневой узел, но подойдет любой узел, который вы внедрили с помощью @FXML), выполните

chooser.showOpenDialog(node.getScene().getWindow());
person James_D    schedule 25.08.2014
comment
и откуда мне взять корневой узел? мне нужно определить fx:id или я полностью упускаю идею? - person Electric Coffee; 25.08.2014
comment
Да, определите fx:id. Но вам не обязательно использовать корневой узел, просто используйте все, для чего у вас уже есть fx:id и что вы вставили в контроллер (все ваши узлы находятся в одной сцене...). Вы также можете сделать Node node = (Node) event.getSource();, но мне это нравится меньше из-за подавленности. - person James_D; 25.08.2014
comment
Не могли бы вы немного уточнить этот ответ? Для начала, что такое узел в этом контексте, и как мне определить fx:id и где? Я скопировал строку сверху, но часть узла все еще не может быть разрешена. - person Sargon1; 26.11.2015
comment
Чтобы прокомментировать запрос @Sargon1: узел — это любой виджет в пользовательском интерфейсе, который наследуется от Node. fx:id — это имя объекта пользовательского интерфейса Java в вашем классе. Вы подключаете связанный компонент fxml через приложение Scenebuilder (также возможно непосредственно в коде fxml, конечно): когда вы открываете файл fxml и выбираете нужный виджет, вы просто устанавливаете id (имя объекта) под правым кодом аккордеона-меню и появляется поле fx:id. - person David Artmann; 26.08.2016

Вам не обязательно придерживаться сцены, созданной в приложении, вы можете:

@FXML protected void locateFile(ActionEvent event) {
    FileChooser chooser = new FileChooser();
    chooser.setTitle("Open File");
    File file = chooser.showOpenDialog(new Stage());
}

Или, если вы хотите продолжать использовать тот же этап, вам нужно передать этап контроллеру до:

    FXMLLoader loader = new FXMLLoader(getClass().getResource("yourFXMLDocument.fxml"));
    Parent root = (Parent)loader.load();
    MyController myController = loader.getController();
    myController.setStage(stage);

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

person Mansueli    schedule 25.08.2014
comment
Я думаю, что лучше установить владельца диалога на правильную стадию, а не на какую-то выдуманную стадию. См. showOpenDialog javadoc Если установлено окно владельца для диалогового окна файла, ввод во все окна в цепочке владельцев диалогового окна блокируется, пока отображается диалоговое окно файла. Если вы не укажете правильный этап, функция блокировки модального диалогового окна FileChooser не включен. Обычно желательно иметь модальную блокировку в FileChooser. - person jewelsea; 26.08.2014
comment
@jewelsea Лучше лучше продолжать использовать одну и ту же сцену, и поэтому я показываю в своем ответе один из способов сделать это. Но следует отметить, что лучшая практика — это не единственная практика. - person Mansueli; 26.08.2014

Из пункта меню

public class SerialDecoderController implements Initializable {

  @FXML
  private MenuItem fileOpen;

  @Override
  public void initialize(URL url, ResourceBundle rb) {
    // TODO
 }    


public void fileOpen (ActionEvent event) {

    FileChooser fileChooser = new FileChooser();
    fileChooser.setTitle("Open Resource File"); 
    fileChooser.showOpenDialog(fileOpen.getParentPopup().getScene().getWindow());

}
person spinnaker15136    schedule 04.11.2017

В качестве альтернативы, что сработало для меня: просто поставьте null.

@FXML
private void onClick(ActionEvent event) {
    File file = fileChooser.showOpenDialog(null);
    if (file != null) {
       //TODO
    }
}
person luke8800gts    schedule 24.02.2018