我有一个使用 SceneBuilder 创建的 JavaFx 项目。 我也在使用 Guice 插件架构。 我有一个 .fxml 文件,其中有一个 Pane ,我想将其作为另一个 .fxml 文件的内容。 有什么简单的方法可以将 .fxml 内容从一个文件链接到另一个文件? 我以前没有使用过 fx.guice 插件架构。使用插件控制是否有更简单的方法?
谢谢!!
最佳答案
这对我们来说是个大问题,因为我们还使用 Guice 和 JavaFX。
tl;dr 我在底部附加了一些代码,我们已经使用了一年多了,现在没有问题。
编辑:我应该提到我们在 fx、guice 存在之前就做了所有这些事情,所以它完全存在于它之外,我可能应该使用它。
是的,但是你必须从 java 修改 View 树,并且你必须实例化两个 Controller 。如果您愿意让 fxml 加载器实例化您的 Controller (我们不是,稍后会更多),那么您只需要按照以下行编写代码
解决方案一:
loadMergedView(){
fxmlLoader.setLocation(getClass().getResource("/com/yourpkg/YourOuterView.fxml"));
Pane outerRoot = fxmlLoader.load();
fxmlLoader.setLocation(getClass().getResource("/com/yourpkg/YourInnerView.fxml"));
Pane innerView = fxmlLoader.load();
((Region)outerRoot.getChildren().get(2))...getChildren().add(innerView);
}
这不太好,因为这意味着 FX 加载器将尝试为您创建 Controller ,但您可能希望 guice 这样做
幸运的是,您可以调用 setController
(或 setControllerFactory
)来利用 guice,所以现在我们有
解决方案2:
@Inject private OuterController outerController
@Inject private InnerController innerController
loadMergedView(){
fxmlLoader.setLocation(getClass().getResource("/com/yourpkg/YourOuterView.fxml"));
//using the setControllerFactory instead of the setController
//means you can still declare the controller type in FXML
//which is good for our IDE intelliJ and general readability
fxmlLoader.setControllerFactory(() -> outerController);
Pane outerRoot = fxmlLoader.load();
fxmlLoader.setLocation(getClass().getResource("/com/yourpkg/YourInnerView.fxml"));
fxmlLoader.setControllerFactory(() -> innerController);
Pane innerView = fxmlLoader.load();
((Region)outerRoot.getChildren().get(2))...getChildren().add(innerView);
}
哪个更好,但需要第 3 方来加载您的组件。您真正想要的,即依赖注入(inject),是首先解析 subview ,并将其作为父 View 解析的一部分。
对我们来说,这将我们带到
解决方案 3:
class OuterController{
@FXML Pane rootPane;
@FXML Stuff otherStuffBoundInFXML;
@FXML AnchorPane innerContactPaneOne;
@Inject
public OuterController(InnerController inner, FXMLLoader loader){
loader.setControllerFactory(type -> this);
loader.setLocation(getClass().getResource("/com/yourpkg/YourOuterView.fxml"));
loader.load();
innerContactPaneOne.getChildren().add(inner.getRootView());
}
}
class InnerController{
@FXML Pane innerContentPaneTwo; //this will be a child of PaneOne in OuterController
@FXML Button otherStuff;
@Inject
public InnerController(FXMLLoader loader){
loader.setControllerFactory(type -> this);
loader.setLocation(getClass().getResource("/com/yourpkg/YourInnerVIew.fxml"));
loader.load();
}
public Node getRootView(){
return innerContentPaneTwo;
}
}
//with somebody calling
OuterController rootController = injector.getInstance(OuterController.class);
最后,以“约定优于配置”的名义,我们创建了一些类(附在下面),它们试图通过反射(reflect) Controller 名称(例如 OuterController
)来“自动”找到 View ) 并且假设它将在与 Controller 的类文件相同的目录中找到一个 FXML View View ,其中单词 controller
替换为 view
(例如外部 View .fxml))。我们还在 java 中利用 super 构造函数顺序中的巧妙技巧来允许我们拥有预先设置的 FXML 值。
现在我们得到:
解决方案4:
class OuterController extends PreloadedFX{
@FXML Pane rootPane;
@FXML Stuff otherStuffBoundInFXML;
@FXML AnchorPane innerContactPaneOne;
@FXML Checkbox importantCheckbox;
@FXML Label importantLabel;
// because of 'PrealoadedFX' getting called first,
// you can actually inline initialize object constants
// like this
private final ObservableBooleanValue isSelected = importantCheckbox.selectedProperty();
// or using an initializer
{
int x = 4;
importantLabel.setText(importantLable.getText() + x);
}
@Inject
public OuterController(InnerController inner, FXMLLoader loader){
super(loader);
innerContactPaneOne.getChildren().add(inner.getRootView());
}
}
class InnerController extends PreloadedFX{
@FXML Pane innerContentPaneTwo; //this will be a child of PaneOne in OuterController
@FXML Button otherStuff;
@Inject
public OuterController(FXMLLoader loader){
super(loader);
}
public Node getRootView(){
return innerContentPaneTwo;
}
}
//with somebody calling
OuterController rootController = injector.getInstance(OuterController.class);
您可以在此处获取 PreloadedFX 和 View-By-Convention 代码的源代码: https://gist.github.com/Groostav/ff35eb2d19b348f2e25c
这和我能够创建这个特定的框架联合一样优雅。
希望对您有所帮助!
关于java - 链接来自不同 fxml 文件的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31457638/