Javafx 2 访问FXML控制器类

Javafx 2 访问FXML控制器类,javafx-2,fxml,Javafx 2,Fxml,我希望随时与FXML控制器类通信,以更新主应用程序或其他阶段屏幕上的信息 这可能吗?我还没有找到做这件事的方法 静态函数可能是一种方法,但它们不能访问窗体的控件 有什么想法吗?在从主屏幕加载对象时,传递已找到并有效的数据的一种方法是使用查找,然后将数据设置在一个不可见的标签内,稍后可以从控制器类中检索该标签。像这样: Parent root = FXMLLoader.load(me.getClass().getResource("Form.fxml")); Label lblData = (La

我希望随时与FXML控制器类通信,以更新主应用程序或其他阶段屏幕上的信息

这可能吗?我还没有找到做这件事的方法

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


有什么想法吗?

在从主屏幕加载对象时,传递已找到并有效的数据的一种方法是使用查找,然后将数据设置在一个不可见的标签内,稍后可以从控制器类中检索该标签。像这样:

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类中。
这样,其他页面用户就不必担心页面的内部结构,比如
标签lblData
是什么以及在哪里


也看看这个。在JavaFX2.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"));
}

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

我发现使用静态函数比这个解决方案更简单,效果更好(至少对我来说)。能够访问控件的关键是拥有一个类的公共静态实例,该实例可以访问所有控件和公共方法。。。但是有人能提供关于答案的更多细节吗?w.r.t.前3行代码和getFooController()的位置在哪里?@adeena,FooController是您在“foo.fxml”中定义的控制器类,代码中没有getFooController()。@UlukBiy-Hmm。。。也许我在尝试做一些与原始海报不同的事情。我在初级阶段有一个FXML应用程序和一个TextArea。我知道如何从其他FXML控制器访问它,但不能从我的包/项目中的任何其他类型的类访问它。@TannerSummers,一旦你得到控制器实例,你需要将它放在某个公共位置(将其视为repo),以便你的应用程序的其他类(模块)可以访问它。我所说的“主阶段”是指具有JavaFX应用程序入口点的类,即具有start(stage)方法的类。在该主类中,您可能更喜欢将控制器实例存储在某个集合中。或者创建一个新的ControllerManager类,其作用类似于存储和访问它们的repo。设计取决于您。此解决方案也适用于以前版本的JavaFX(总的来说,我认为选择的答案必须是首选的,尽管这是巧妙的:首先,您可以有多个控制器,因此您确实希望在
应用程序中有一个静态映射(注意,您总是可以从加载程序中获取控制器)。其次,我们得到了一个
getController()
方法,因此使用它是有意义的。第三,当实际涉及实例操作时,应该避免使用
静态方法,这可能是一般的编码首选项。将控制器存储在静态字段中不是一个好主意。