如何使用Guava获取具体的控制器类型
我在我的JavaFX应用中使用Google Guava来切换内容面板。
@Subscribe
public void handleChangeViewDataModel(ChangeViewEventDataModel event) {
try {
FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(getClass().getResource(event.getViewName())));
loader.setControllerFactory(new ControllerFactory());
Parent root = loader.load();
// change the content pane
contentController.getContent().getChildren().clear();
contentController.getContent().getChildren().add(root);
以及
public class ControllerFactory implements Callback<Class<?>, Object> {
@Override
public Object call(Class<?> controllerType) {
if (controllerType == ContentController.class) return new ContentController();
if (controllerType == ContentHomeController.class) return new ContentHomeController();
if (controllerType == ContentOneController.class) return new ContentOneController();
throw new RuntimeException("Controller of type '" + controllerType.getSimpleName() + "' is not supported!");
}
}
如何获取控制器的具体实现类,以便调用其他方法来设置UI元素?
我需要类似这样的:
ContentOneController contentOneController = loader.getController();
contentOneController.setLabelText(event.getNewData());
或者是否有其他推荐的做法?
解决方案
是否有其他推荐的方法?
我建议让控制器来承担初始化工作,向它提供完成初始化所需的数据,而不是像你现在尝试的那样从外部调用一个方法来执行初始化。为此,你可以按如下方式进行重构:
首先,通过构造函数让控制器获得对事件的访问权,然后只需在通常的 initialize() 方法中完成初始化:
public class ContentOneController {
private ChangeViewEventDataModel event ;
public ContentOneController(ChangeViewEventDataModel event) {
this.event = event;
}
public ContentOneController() {
this(null);
}
@FXML
private void initialize() {
if (event != null) {
setLabelText(event.getNewData());
}
}
// exisiting code ...
}
现在你只需要修改控制器工厂,使其能够访问事件:
public class ControllerFactory implements Callback<Class<?>, Object> {
private ChangeViewEventDataModel event ;
public ControllerFactory(ChangeViewEventDataModel event) {
this.event = event;
}
@Override
public Object call(Class<?> controllerType) {
if (controllerType == ContentController.class) return new ContentController();
if (controllerType == ContentHomeController.class) return new ContentHomeController();
if (controllerType == ContentOneController.class) return new ContentOneController(event);
throw new RuntimeException("Controller of type '" + controllerType.getSimpleName() + "' is not supported!");
}
}
最后只需把事件传递给控制器工厂:
@Subscribe
public void handleChangeViewDataModel(ChangeViewEventDataModel event) {
try {
FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(getClass().getResource(event.getViewName())));
loader.setControllerFactory(new ControllerFactory(event));
Parent root = loader.load();
// change the content pane
contentController.getContent().getChildren().clear();
contentController.getContent().getChildren().add(root);
} catch (Exception e) {
// ...
}
}
现在控制器将自行处理初始化,你就不需要在外部调用 setLabelText(...) 方法。这将是我首选的方法,因为初始化发生在“自然”的位置。
如果你愿意不进行重构,你可以只使用带模式匹配的switch(甚至只是使用 if 语句序列,结合 instanceof)。这看起来不太可取,因为它需要对控制器类型进行第二轮测试,超出了你在控制器工厂中已经需要实现的内容:
@Subscribe
public void handleChangeViewDataModel(ChangeViewEventDataModel event) {
try {
FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(getClass().getResource(event.getViewName())));
loader.setControllerFactory(new ControllerFactory(event));
Parent root = loader.load();
// change the content pane
contentController.getContent().getChildren().clear();
contentController.getContent().getChildren().add(root);
switch (loader.getController()) {
case ContentOneController c1c -> c1c.setLabelText(event.getNewData());
// other cases as needed
default -> {}
}
} catch (Exception e) {
// ...
}
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。