访问FXML控制器类

bet*_*man 58 javafx-2 fxml

我想随时与FXML控制器类进行通信,以便从主应用程序或其他阶段更新屏幕上的信息.

这可能吗?我还没有找到任何办法.

静态函数可能是一种方式,但它们无法访问表单的控件.

有任何想法吗?

Ulu*_*Biy 97

你可以从中获取控制器 FXMLLoader

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

将它存储在主阶段并提供getFooController()getter方法.
从其他类或阶段,每当您需要刷新加载的"foo.fxml"页面时,从其控制器询问它:

getFooController().updatePage(strData);
Run Code Online (Sandbox Code Playgroud)

updatePage()可以是这样的:

// ...
@FXML private Label lblData;
// ...
public void updatePage(String data){
    lblData.setText(data);
}
// ...
Run Code Online (Sandbox Code Playgroud)

在FooController类中.
这样,其他页面用户就不会对页面的内部结构感到烦恼,例如什么和在哪里Label lblData.

另请查看/sf/answers/750307841/.在JavaFX 2.2 FXMLLoader中得到了改进.

  • 我发现使用静态函数比这个解决方案更容易并且效果更好(至少对我而言).能够访问控件的关键是拥有一个可以访问所有控件和公共方法的类的公共静态实例. (2认同)

Dat*_*uti 18

只是为了帮助澄清已接受的答案,并为其他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();
}
Run Code Online (Sandbox Code Playgroud)

现在,我们需要做的就是访问控制器类是将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();
}
Run Code Online (Sandbox Code Playgroud)


Cal*_*leb 8

另一种解决方案是从控制器类中设置控制器,如此...

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

}
Run Code Online (Sandbox Code Playgroud)

这是我喜欢使用的解决方案,因为代码有点混乱,无法创建一个功能齐全的FXMLLoader实例,可正确处理本地资源等

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

@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));
}
Run Code Online (Sandbox Code Playgroud)