我想构建一个javafx应用程序,其中fxml文档及其控制器都存储在数据库中。 多亏了jewelsea,我可以使用以下代码动态加载fxml文档:
String fxmlDocument = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"\n" +
"<?import javafx.scene.control.Button?>\n" +
"<?import javafx.scene.layout.BorderPane?>\n" +
"\n" +
"\n" +
"<BorderPane maxHeight=\"-Infinity\" maxWidth=\"-Infinity\" minHeight=\"-Infinity\" minWidth=\"-Infinity\" prefHeight=\"400.0\" prefWidth=\"600.0\" xmlns=\"http://javafx.com/javafx/8.0.171\" xmlns:fx=\"http://javafx.com/fxml/1\" fx:controller=\"main.ControllerClass\">\n" +
" <center>\n" +
" <Button fx:id=\"button\" mnemonicParsing=\"false\" onAction=\"#onButtonClicked\" text=\"Button\" BorderPane.alignment=\"CENTER\" />\n" +
" </center>\n" +
"</BorderPane>";
FXMLLoader loader = new FXMLLoader();
BorderPane layout = (BorderPane) loader.load(
new ByteArrayInputStream(fxmlDocument.getBytes())
);
我的控制器首先存储在ControllerClass.java文件中
package main;
import javafx.scene.control.Button;
import javafx.event.ActionEvent;
public class ControllerClass {
public Button button;
public void onButtonClicked(ActionEvent event){
System.out.println("Button's clicked");
}
}
效果很好。
但是现在我的控制器存储在一个字符串中,因此我使用此链接[inmemory]:https://github.com/trung/InMemoryJavaCompiler来编译和实例化我的控制器,如下所示:
StringBuilder fxmlController = new StringBuilder();
fxmlController.append("package main;\n");
fxmlController.append("import javafx.scene.control.Button;\n");
fxmlController.append("import javafx.event.ActionEvent;\n");
fxmlController.append("import java.util.ArrayList;\n");
fxmlController.append("import java.util.List;\n");
fxmlController.append("public class ControllerClass {\n");
fxmlController.append(" public Button button;\n");
fxmlController.append(" public void onButtonClicked(ActionEvent event){\n");
fxmlController.append(" System.out.println(\"ControllerClass called\");");
fxmlController.append(" }");
fxmlController.append(" public List<String> test() {");
fxmlController.append(" List<String> supplierNames = new ArrayList<String>();");
fxmlController.append(" supplierNames.add(\"sup1\");");
fxmlController.append(" supplierNames.add(\"sup2\");");
fxmlController.append(" supplierNames.add(\"sup3\");");
fxmlController.append(" supplierNames.add(\"sup4\");");
fxmlController.append(" System.out.println(supplierNames.get(3));");
fxmlController.append(" return supplierNames;");
fxmlController.append(" }");
fxmlController.append("}");
Class<?> controllerClass = InMemoryJavaCompiler.newInstance().ignoreWarnings().compile("main.ControllerClass", fxmlController.toString());
List<?> listSize = (List<?>) controllerClass.getMethod("test").invoke(controllerClass.newInstance());
System.out.println("listSize.size()=" + listSize.size());
运行代码时,结果是:
sup4
res.size()=4
这意味着,如果我将fxml文档和控制器动态编译/实例化/加载在一起时出现错误,则控制器将正确编译并实例化,但是
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:748)
Caused by: javafx.fxml.LoadException:
unknown path:7
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:922)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2425)
at main.Main.start(Main.java:111)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
... 1 more
Caused by: java.lang.ClassNotFoundException: main.ControllerClass
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:920)
... 16 more
Exception running application main.Main
Process finished with exit code 1
问题是:
Caused by: javafx.fxml.LoadException:
unknown path:7
我做错了什么,因为我的控制器已正确编译/实例化,但FXMLLoader并没有将其确认。 你能帮忙吗? 预先感谢。