访问FXML控制器类
我想随时与FXML控制器类进行通信,从主应用程序或其他阶段更新屏幕上的信息。
这可能吗? 我没有find任何方法来做到这一点。
静态函数可能是一种方法,但他们无法访问窗体的控件。
有任何想法吗?
你可以从FXMLLoader
获得控制器
FXMLLoader fxmlLoader = new FXMLLoader(); Pane p = fxmlLoader.load(getClass().getResource("foo.fxml").openStream()); FooController fooController = (FooController) fxmlLoader.getController();
将其存储在主要阶段并提供getFooController()getter方法。
从其他类或阶段,每当需要刷新加载的“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
得到了改进。
另一个解决scheme是从您的控制器类设置控制器,就像这样…
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); } }
这是我喜欢使用的解决scheme,因为代码是有点混乱,以创build一个function齐全的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的其他人节省了一些时间:
对于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(); }
在主屏幕上加载对象时,传递数据的一种方法是使用lookup,然后将数据设置在一个不可见的标签中,以便以后可以从控制器类中检索。 喜欢这个:
Parent root = FXMLLoader.load(me.getClass().getResource("Form.fxml")); Label lblData = (Label) root.lookup("#lblData"); if (lblData!=null) lblData.setText(strData);
这有效,但必须有更好的方法。