Вопрос по – Доступ к классу контроллера FXML

56

Я хотел бы общаться с классом контроллера FXML в любое время, чтобы обновлять информацию на экране из основного приложения или других этапов.

Это возможно? Я не нашел никакого способа сделать это.

Статические функции могут быть способом, но у них нет доступа к элементам управления формы.

Любые идеи

Ваш Ответ

4   ответа
92

Вы можете получить контроллер отFXMLLoader

FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource("foo.fxml").openStream());
FooController fooController = (FooController) fxmlLoader.getController();

сохраните его на своем основном этапе и предоставьте метод getFooController ().
Из других классов или этапов каждый раз, когда вам нужно обновить загруженную страницу «foo.fxml», запрашивайте ее у контроллера:

getFooController().updatePage(strData);

updatePage () может быть что-то вроде:

// ...
@FXML private Label lblData;
// ...
public void updatePage(String data){
    lblData.setText(data);
}
// ...

в классе FooController.
Таким образом, другие пользователи страницы не беспокоятся о внутренней структуре страницы, например о том, что и гдеLabel lblData является

Также посмотритеhttps: //stackoverflow.com/a/10718683/68249. В JavaFX 2.2FXMLLoader улучшается.

Я обнаружил, что использование статических функций проще и работает лучше, чем это решение (по крайней мере, для меня). Ключом к возможности доступа к элементам управления является наличие открытого статического экземпляра класса, который имеет доступ ко всем элементам управления и открытым методам. betaman
Я знаю, что это старый вопрос ... но кто-нибудь может предоставить более подробную информацию об ответе w.r.t. где первые 3 строки кода и куда идет getFooController ()? adeena
@ adeena, FooController - это класс контроллеров, определенный вами в "foo.fxml", и в коде нет getFooController (). Uluk Biy
@ UlukBiy Хм ... может быть, я пытаюсь сделать что-то другое, чем оригинальный постер. У меня есть приложение FXML и TextArea на начальном этапе. Я выяснил, как получить к нему доступ из других контроллеров FXML, но не из какого-либо другого типа класса в моем пакете / проекте. adeena
@ TannerSummers, как только вы получите экземпляр контроллера, вам нужно поместить его в какое-то обычное место (представьте, что это репозиторий), чтобы другие классы (модули) вашего приложения могли получить к нему доступ. Под «основным этапом» я подразумевал класс, имеющий точку входа вашего приложения JavaFX, а именно класс, в котором есть метод start (Stage stage). В этом основном классе вы можете предпочесть хранить экземпляры контроллера в некоторой коллекции. Или создайте новый класс ControllerManager, который действует как хранилище для хранения и доступа к ним. Дизайн зависит от вас. Uluk Biy
13

Просто чтобы помочь уточнить принятый ответ и, возможно, сэкономить немного времени для тех, кто не знаком с JavaFX:

Для приложения JavaFX FXML NetBeans автоматически сгенерирует ваш метод запуска в основном классе следующим образом:

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}

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

//Static global variable for the controller (where MyController is the name of your controller class
static MyController myControllerHandle;

@Override
public void start(Stage stage) throws Exception {
    //Set up instance instead of using static load() method
    FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
    Parent root = loader.load();

    //Now we have access to getController() through the instance... don't forget the type cast
    myControllerHandle = (MyController)loader.getController();

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}
очень хороший ответ с четкими комментариями! user2407334
7

чтобы установить контроллер из вашего класса контроллеров, вот так ...

public class Controller implements javafx.fxml.Initializable {

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // Implementing the Initializable interface means that this method
        // will be called when the controller instance is created
        App.setController(this);
    }

}

Это решение, которое я предпочитаю использовать, так как код несколько запутан для создания полнофункционального экземпляра FXMLLoader, который правильно обрабатывает локальные ресурсы и т. Д.

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("/sample.fxml"));
}

проти

@Override
public void start(Stage stage) throws Exception {
    URL location = getClass().getResource("/sample.fxml");
    FXMLLoader loader = createFXMLLoader(location);
    Parent root = loader.load(location.openStream());
}

public FXMLLoader createFXMLLoader(URL location) {
    return new FXMLLoader(location, null, new JavaFXBuilderFactory(), null, Charset.forName(FXMLLoader.DEFAULT_CHARSET_NAME));
}
Это решение работает и для предыдущих версий JavaFX (<2.2). Neil
2

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

Parent root = FXMLLoader.load(me.getClass().getResource("Form.fxml"));
Label lblData = (Label) root.lookup("#lblData");
if (lblData!=null) lblData.setText(strData); 

Это работает, но должен быть лучший способ.

Похожие вопросы