访问 FXML 控制器类

我想在任何时候与一个 FXML 控制器类通信,从主应用程序或其他阶段更新屏幕上的信息。

这可能吗? 我还没找到办法。

静态函数可能是一种方法,但它们不能访问窗体的控件。

有什么想法吗?

107648 次浏览

在从 Main 屏幕加载对象时,传递我已经找到并且可以工作的数据的一种方法是使用查找,然后在一个不可见的标签中设置数据,稍后我可以从控制器类中检索这些数据。像这样:

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

这能行,但肯定有更好的办法。

您可以从 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得到了改进。

另一个解决方案是从控制器类中设置控制器,如下所示..。

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

VS

@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 将在主类中自动生成 start 方法,如下所示:

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