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

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

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

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

какие идеи?

4 ответов


вы можете получить контроллер от 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/682495. В JavaFX 2.2 FXMLLoader улучшается.


просто, чтобы помочь уточнить принятый ответ и, возможно, сэкономить немного времени для других, которые являются новыми для 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();
}

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

//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();
}

другое решение-установить контроллер из вашего класса контроллера, например...

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));
}

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

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

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