【发布时间】:2020-09-25 09:56:29
【问题描述】:
我正在编写一个库来简化 JavaFX 应用程序的开发,为了使其可用于 Java 模块化系统,我需要在另一个 java 模块(客户端模块)中获取 FXML 文件的 URL 并传递它到我的库(库模块)中的FXMLLoader。
总而言之: 我需要获取客户端模块中的 FXML 文件的资源 URL,以便在库模块中读取。
我试过了:
Accessing resource files from external modules
Load a Resource from another Module in Java (With Maven)
我最近的尝试:
private void addController(ControllerInfo info, Class<? extends SimpleController> controllerClass) throws IOException {
String filename = info.FXMLFile();
if (!filename.startsWith("/"))
filename = "/" + filename;
ModuleReference ref=ModuleLayer.boot().configuration().findModule(moduleName).map(ResolvedModule::reference).get();
ModuleReader resReader=ref.open();
URL url = resReader.find(filename).get().toURL();
controllerClasses.put(info.Id(), controllerClass);
info.Type().getAction().addController(info, url, controllerClass);
}
在客户端模块中,我将资源放在资源文件夹中的io/github/ossnass/languageexample 文件夹中,module-info.java 如下所示:
module languageExample {
requires javafx.controls;
requires javafx.fxml;
requires simplefx;
opens io.github.ossnass.languageexample.gui to javafx.fxml;
opens io.github.ossnass.languageexample to simplefx;
exports io.github.ossnass.languageexample.app;
}
FXML 控制器类:
@ControllerInfo(Id = "LangMain", FXMLFile = "/io/github/ossnass/languageexample/langexample.fxml", Type = ContollerType.SINGLE_INSTANCE_ON_STARTUP)
public class LangExampleMain extends SimpleController {
@Override
protected void userInit() {
}
@Override
protected void onStageShowUser() {
}
@FXML
private Button btnMessage;
@FXML
void btnMessageClick(ActionEvent event) {
QuickActions.showInfoMessage(null,
resources.getString("InfoHeader"),
resources.getString("InfoBody"),
this);
}
}
我收到以下错误:
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:148)
at io.github.ossnass.fx.ControlMaster.addController(ControlMaster.java:179)
at io.github.ossnass.fx.ControlMaster.findControllers(ControlMaster.java:198)
at io.github.ossnass.fx.ControlMaster.initControlMaster(ControlMaster.java:134)
at io.github.ossnass.languageexample.app.Main.start(Main.java:11)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
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:277)
... 1 more
资源文件的URL路径为:/io/github/ossnass/languageexample/langexample.fxml
请注意,我使用的是 Maven,并且我将 FXML 放在了 resources 目录中。
我正在开发的库可以在SimpleFX找到
【问题讨论】:
-
你不应该这样做
filename = "/" + filename;。资源永远不会以斜线开头,除非它们是Class.getResource或Class.getResourceAsStream的参数。也就是说,ClassLoader.getResource 将满足您的需求。你不需要明确的 ModuleReader。 -
我尝试了您的建议,但无济于事,网址仍然为空。
-
如果
info.FXMLFile();返回一个URL而不是一个字符串可能会更容易?让调用者负责调用 Class.getResource。
标签: java maven java-platform-module-system javafx-11