2012-05-25 3 views
41

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

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

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

Любые идеи?

ответ

69

Вы можете получить контроллер от 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.

+2

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

+0

Я знаю, что это старый вопрос ... но может ли кто-нибудь предоставить более подробную информацию о ответе w.r.t. где первые 3 строки кода и где getFooController() идет? – adeena

+0

@adeena, FooController - это класс контроллера, определенный вами в «foo.fxml», и в коде отсутствует getFooController(). –

2

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

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

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

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

Это решение работает и для предыдущих версий JavaFX (<2.2). – Neil

7

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

очень хороший ответ с четкими комментариями! – user2407334

Смежные вопросы