我尝试了以下代码,并被迫启动名为Viewer
的JavaFx应用程序而不直接调用方法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()"
}
}
然后它可以正常工作并启动。
所以我很好奇为什么会发生这种情况,或者我是以不正确的格式编写代码。
谢谢。
答案 0 :(得分:7)
由于launch
是一个静态方法,因此在编译之后,不能通过检查堆栈以外的方式确定应用程序类
Application.launch("");
在字节码中与
结尾相同Viewer.launch("");
只有在堆栈中的某个地方找到Application
类时,检查堆栈才有效。这就是为什么需要从launch
类调用Application
。
但是有另一种选择:
您可以将Application
课程传递给the overloaded version of the launch
method:
Application.launch(Viewer.class, "");
答案 1 :(得分:4)
It doesn't必须从Application
子类中启动。
你可以做到
package Freelance;
import javafx.application.Application ;
public class Test
{
public static void main(String[] args)
{
Application.launch(Viewer.class, args);
}
}
答案 2 :(得分:1)
当您查看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循环遍历堆栈跟踪。这意味着:您需要在提供launch(String... args)
方法的类中调用start()
方法。