Gluon Afterburner getPresenter() 仅返回 NoSuchElementException:不存在任何值
我使用 Glisten Afterburner (v2.1.0) 从 Gluon Start 生成一个简单的应用程序。这会生成三个类,其中两个是 Main 和 AppViewManager,使用 glisten.afterburner AppView 和 AppViewRegistry。我向生成的代码添加了一个附加视图(“其他”),并向 AppViewManager 添加了方法以获取与视图关联的 Presenter。
生成的 Main 类如下所示,我在其中添加了获取 Presenters 的静态调用: getMainPresenter() 和 getOtherPresenter():
public class Main extends Application {
private final AppManager appManager = AppManager.initialize(this::postInit);
@Override
public void init() {
AppViewManager.registerViewsAndDrawer();
}
@Override
public void start(Stage stage) {
appManager.start(stage);
}
private void postInit(Scene scene) {
:
// Get Main Presenter
AppViewManager.getMainPresenter();
// Get Other Presenter
AppViewManager.getOtherPresenter();
}
:
}
AppViewManager 如下所示,我添加了附加视图(“其他”)并添加了获取 Presenters 的方法与视图相关联。在注册视图时,我添加了一些输出来查看发生了什么:
public class AppViewManager {
private static final AppViewRegistry REGISTRY = new AppViewRegistry();
public static final AppView MAIN_VIEW = view("Home", MainPresenter.class, MaterialDesignIcon.HOME, SHOW_IN_DRAWER, HOME_VIEW, SKIP_VIEW_STACK);
public static final AppView OTHER_VIEW = view("Other", OtherPresenter.class, MaterialDesignIcon.NOTE, SHOW_IN_DRAWER, SKIP_VIEW_STACK);
private static AppView view(String title, Class<?> presenterClass, MaterialDesignIcon menuIcon, AppView.Flag... flags ) {
return REGISTRY.createView(name(presenterClass), title, presenterClass, menuIcon, flags);
}
private static String name(Class<?> presenterClass) {
return presenterClass.getSimpleName().toUpperCase(Locale.ROOT).replace("PRESENTER", "");
}
public static void registerViewsAndDrawer()
{
for (AppView view : REGISTRY.getViews())
{
// What's in the REGISTRY?
System.out.println("==> View: " +view.getId()+ ", Presenter: " +view.getPresenterClass().getCanonicalName());
// Not sure what the following does, the javadoc is blank!
view.registerView();
}
:
}
/**
* Get MainPresenter.
* See: .../AppViewRegistry.html#getPresenter(com.gluonhq.charm.glisten.afterburner.AppView)
*/
public static void getMainPresenter()
{
MainPresenter mp = (MainPresenter)MAIN_VIEW.getPresenter().get();
System.out.println("..Presenter..> " +mp.toString());
}
public static void getOtherPresenter()
{
OtherPresenter op = (OtherPresenter)OTHER_VIEW.getPresenter().get();
System.out.println("..OtherPresenter..> " +op.toString());
}
}
OtherPresenter 是一个简单的声明:
public class OtherPresenter {
public void initialize() {}
}
OtherPresenter FXML 是:
<View fx:id="other" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.runtheworld.sample.OtherPresenter">
<center>
<VBox styleClass="box">
<children>
<Label text="Other!" />
</children>
</VBox>
</center>
</View>
REGISTRY 输出中的内容符合预期(除了我期望的是“HOME_VIEW”而不是“home”):
==> View: home, Presenter: com.runtheworld.sample.MainPresenter
==> View: OTHER_VIEW, Presenter: com.runtheworld.sample.OtherPresenter
但无论我在哪里进行 getOtherPresenter() 调用,它都会返回:“Caused by: java.util.NoSuchElementException: No value present”。然而, getMainPresenter() 调用是有效的。事实上,该应用程序可以正常运行,显示 OtherPresenter(显示“其他!”),但仍然抛出“无值”。
为什么 Main 工作但其他不工作,是否有一些我错过的设置/初始化?
这是所有输出:
==> View: home, Presenter: com.runtheworld.sample.MainPresenter
==> View: OTHER_VIEW, Presenter: com.runtheworld.sample.OtherPresenter
Apr 03, 2022 11:24:16 AM com.gluonhq.attach.util.Platform <clinit>
INFO: [Gluon Attach] System Property javafx.platform is not defined. Platform will be set to Platform.DESKTOP
..MainPresenter..> com.runtheworld.sample.MainPresenter@686bbb76
java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:143)
at com.runtheworld.sample.AppViewManager.getOtherPresenter(AppViewManager.java:54)
at com.runtheworld.sample.Main.postInit(Main.java:41)
at com.gluonhq.charm.glisten.application.AppManager.continueInit(AppManager.java:328)
at com.gluonhq.charm.glisten.application.AppManager.start(AppManager.java:288)
at com.runtheworld.sample.Main.start(Main.java:24)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:290)
at java.base/java.lang.Thread.run(Thread.java:833)
编辑: 我决定避开 afterburner,简单地构建一个视图,如下所示:
public class OtherView {
public static final String OTHER_VIEW = "OTHER_VIEW";
public AbstractMap.SimpleEntry<String,AbstractMap.SimpleEntry<View,Presenter>> getViewController() {
try {
FXMLLoader f = new FXMLLoader(OtherView.class.getResource("/path/to/other.fxml"), ResourceBundle.getBundle("path.to.other"));
View view = f.load();
OtherPresenter controller = f.getController();
return new AbstractMap.SimpleEntry(OTHER_VIEW,new AbstractMap.SimpleEntry(view,controller));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
视图和控制器在 FXML 中定义,这将视图名称与视图及其关联的控制器联系起来。 getViewController() 是从 Main.init() 调用的。
I generate a simple app from Gluon Start with Glisten Afterburner (v2.1.0). This generates three classes of which two are Main and AppViewManager using glisten.afterburner AppView and AppViewRegistry. I add an additional View to the generated code ("Other") and I add methods to AppViewManager to get the Presenter associated with a View.
The generated Main class looks like the following to which I have added the static calls to get Presenters: getMainPresenter() and getOtherPresenter():
public class Main extends Application {
private final AppManager appManager = AppManager.initialize(this::postInit);
@Override
public void init() {
AppViewManager.registerViewsAndDrawer();
}
@Override
public void start(Stage stage) {
appManager.start(stage);
}
private void postInit(Scene scene) {
:
// Get Main Presenter
AppViewManager.getMainPresenter();
// Get Other Presenter
AppViewManager.getOtherPresenter();
}
:
}
AppViewManager looks like the following where I added the additional View ("Other") and added methods to get Presenters associated with Views. In registering Views, I added some output to see what is going on:
public class AppViewManager {
private static final AppViewRegistry REGISTRY = new AppViewRegistry();
public static final AppView MAIN_VIEW = view("Home", MainPresenter.class, MaterialDesignIcon.HOME, SHOW_IN_DRAWER, HOME_VIEW, SKIP_VIEW_STACK);
public static final AppView OTHER_VIEW = view("Other", OtherPresenter.class, MaterialDesignIcon.NOTE, SHOW_IN_DRAWER, SKIP_VIEW_STACK);
private static AppView view(String title, Class<?> presenterClass, MaterialDesignIcon menuIcon, AppView.Flag... flags ) {
return REGISTRY.createView(name(presenterClass), title, presenterClass, menuIcon, flags);
}
private static String name(Class<?> presenterClass) {
return presenterClass.getSimpleName().toUpperCase(Locale.ROOT).replace("PRESENTER", "");
}
public static void registerViewsAndDrawer()
{
for (AppView view : REGISTRY.getViews())
{
// What's in the REGISTRY?
System.out.println("==> View: " +view.getId()+ ", Presenter: " +view.getPresenterClass().getCanonicalName());
// Not sure what the following does, the javadoc is blank!
view.registerView();
}
:
}
/**
* Get MainPresenter.
* See: .../AppViewRegistry.html#getPresenter(com.gluonhq.charm.glisten.afterburner.AppView)
*/
public static void getMainPresenter()
{
MainPresenter mp = (MainPresenter)MAIN_VIEW.getPresenter().get();
System.out.println("..Presenter..> " +mp.toString());
}
public static void getOtherPresenter()
{
OtherPresenter op = (OtherPresenter)OTHER_VIEW.getPresenter().get();
System.out.println("..OtherPresenter..> " +op.toString());
}
}
OtherPresenter is a simple declaration:
public class OtherPresenter {
public void initialize() {}
}
The OtherPresenter FXML is:
<View fx:id="other" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.runtheworld.sample.OtherPresenter">
<center>
<VBox styleClass="box">
<children>
<Label text="Other!" />
</children>
</VBox>
</center>
</View>
What's in the REGISTRY output is as expected (except I would have expected 'HOME_VIEW' rather than 'home'):
==> View: home, Presenter: com.runtheworld.sample.MainPresenter
==> View: OTHER_VIEW, Presenter: com.runtheworld.sample.OtherPresenter
But no matter where I make the getOtherPresenter() call, it returns: "Caused by: java.util.NoSuchElementException: No value present". The getMainPresenter() call, however, works. In fact, the app functions, showing OtherPresenter (displaying "Other!") but still throwing "No value".
Why does Main work but not Other, is there some setup/init I have missed?
Here's all the output:
==> View: home, Presenter: com.runtheworld.sample.MainPresenter
==> View: OTHER_VIEW, Presenter: com.runtheworld.sample.OtherPresenter
Apr 03, 2022 11:24:16 AM com.gluonhq.attach.util.Platform <clinit>
INFO: [Gluon Attach] System Property javafx.platform is not defined. Platform will be set to Platform.DESKTOP
..MainPresenter..> com.runtheworld.sample.MainPresenter@686bbb76
java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:143)
at com.runtheworld.sample.AppViewManager.getOtherPresenter(AppViewManager.java:54)
at com.runtheworld.sample.Main.postInit(Main.java:41)
at com.gluonhq.charm.glisten.application.AppManager.continueInit(AppManager.java:328)
at com.gluonhq.charm.glisten.application.AppManager.start(AppManager.java:288)
at com.runtheworld.sample.Main.start(Main.java:24)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:290)
at java.base/java.lang.Thread.run(Thread.java:833)
EDIT:
I decided to eschew afterburner and simply built a View as follows:
public class OtherView {
public static final String OTHER_VIEW = "OTHER_VIEW";
public AbstractMap.SimpleEntry<String,AbstractMap.SimpleEntry<View,Presenter>> getViewController() {
try {
FXMLLoader f = new FXMLLoader(OtherView.class.getResource("/path/to/other.fxml"), ResourceBundle.getBundle("path.to.other"));
View view = f.load();
OtherPresenter controller = f.getController();
return new AbstractMap.SimpleEntry(OTHER_VIEW,new AbstractMap.SimpleEntry(view,controller));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
The View and Controller are defined in the FXML and this ties the View name to the View and its associated Controller. getViewController() is called from Main.init().
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论