[英]Why does a JavaFx Application HAVE to be launched from within its own class?
我嘗試了以下代碼,並被迫啟動我的JavaFx應用程序Viewer
而沒有直接調用方法launch
。
這是JavaFx類:
package Freelance;
public class Viewer extends Application
{
private WebEngine myWebEngine;
public void start(Stage stage)
{
stage.setTitle("Browser");
WebView myBrowser = new WebView();
myWebEngine = myBrowser.getEngine();
myWebEngine.getLoadWorker().exceptionProperty().addListener(new ChangeListener<Throwable>()
{
@Override
public void changed(ObservableValue<? extends Throwable> observableValue, Throwable oldException,
Throwable exception)
{
System.out.println("WebView encountered an exception loading a page: " + exception);
}
});
myBrowser.setPrefSize(1600, 900);
BorderPane root = new BorderPane();
root.setCenter(myBrowser);
stage.setScene(new Scene(root));
stage.show();
myWebEngine.load("http://www.google.com/");
}
public static void run()
{
launch("");
}
}
現在,當我嘗試從類似的單獨類中啟動它時:
package Freelance;
public class Test
{
public static void main(String[] args)
{
Viewer.launch();
}
}
我收到以下錯誤:
Exception in thread "main" java.lang.RuntimeException: Error: class Freelance.Test is not a subclass of javafx.application.Application
at javafx.application.Application.launch(Application.java:254)
at Freelance.Test.main(Test.java:8)
但是,如果我像這樣更改Test
類:
package Freelance;
public class Test
{
public static void main(String[] args)
{
Viewer.run(); // Changed from using "launch()" to "run()"
}
}
然后它可以正常運行並啟動。
所以我只是好奇為什么會發生這種情況,或者我是否以錯誤的格式編寫代碼。
謝謝。
由於launch
是靜態方法,因此,除了檢查堆棧外,無法通過其他方式確定應用程序類,因為在編譯之后
Application.launch("");
最終在字節碼中與
Viewer.launch("");
僅當您可以在堆棧中的某個位置找到Application
類時,才檢查堆棧,這就是為什么需要從Application
類調用launch
原因。
但是,還有一種選擇:
您可以將Application
類傳遞給launch
方法的重載版本 :
Application.launch(Viewer.class, "");
當您查看javafx.application.Apllication
的launch(String... args)
,您將找到以下代碼:
public static void launch(String... args) {
// Figure out the right class to call
StackTraceElement[] cause = Thread.currentThread().getStackTrace();
boolean foundThisMethod = false;
String callingClassName = null;
for (StackTraceElement se : cause) {
// Skip entries until we get to the entry for this class
String className = se.getClassName();
String methodName = se.getMethodName();
if (foundThisMethod) {
callingClassName = className;
break;
} else if (Application.class.getName().equals(className)
&& "launch".equals(methodName)) {
foundThisMethod = true;
}
}
if (callingClassName == null) {
throw new RuntimeException("Error: unable to determine Application class");
}
try {
Class theClass = Class.forName(callingClassName, false,
Thread.currentThread().getContextClassLoader());
if (Application.class.isAssignableFrom(theClass)) {
Class<? extends Application> appClass = theClass;
LauncherImpl.launchApplication(appClass, args);
} else {
throw new RuntimeException("Error: " + theClass
+ " is not a subclass of javafx.application.Application");
}
} catch (RuntimeException ex) {
throw ex;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
如您所見,foreach循環遍歷堆棧跟蹤。 這意味着:您需要從提供start()
方法的類中調用launch(String... args)
start()
方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.