[英]Why does a JavaFx Application HAVE to be launched from within its own class?
I tried the following code and was forced to launch my JavaFx application called Viewer
without directly calling the method launch
. 我尝试了以下代码,并被迫启动我的JavaFx应用程序
Viewer
而没有直接调用方法launch
。
Here is the JavaFx class: 这是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("");
}
}
Now when I try to launch this from a separate class like so: 现在,当我尝试从类似的单独类中启动它时:
package Freelance;
public class Test
{
public static void main(String[] args)
{
Viewer.launch();
}
}
I get the following error: 我收到以下错误:
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)
However, if I change the Test
class like so: 但是,如果我像这样更改
Test
类:
package Freelance;
public class Test
{
public static void main(String[] args)
{
Viewer.run(); // Changed from using "launch()" to "run()"
}
}
Then it works and launches properly. 然后它可以正常运行并启动。
So I was just curious as to why this happens or if I am writing the code in an incorrect format. 所以我只是好奇为什么会发生这种情况,或者我是否以错误的格式编写代码。
Thank you. 谢谢。
Since launch
is a static method, the application class cannot be determined by means other than inspecting the stack, since after compilation 由于
launch
是静态方法,因此,除了检查堆栈外,无法通过其他方式确定应用程序类,因为在编译之后
Application.launch("");
ends up the same in the bytecode as 最终在字节码中与
Viewer.launch("");
Inspecting the stack only works, if you can find the Application
class somewhere in the stack, which is why launch
needs to be called from the Application
class. 仅当您可以在堆栈中的某个位置找到
Application
类时,才检查堆栈,这就是为什么需要从Application
类调用launch
原因。
There is an alternative however: 但是,还有一种选择:
You could pass the Application
class to the overloaded version of the launch
method : 您可以将
Application
类传递给launch
方法的重载版本 :
Application.launch(Viewer.class, "");
It doesn't have to be launched from within the Application
subclass. 不必从
Application
子类内部启动它 。
You can do 你可以做
package Freelance;
import javafx.application.Application ;
public class Test
{
public static void main(String[] args)
{
Application.launch(Viewer.class, args);
}
}
When you take a look at javafx.application.Apllication
's implementation of launch(String... args)
, you will find this code: 当您查看
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);
}
}
As you see, the foreach-loop iterates over the stack-trace. 如您所见,foreach循环遍历堆栈跟踪。 This means: your need to call the
launch(String... args)
method from within the class providing the start()
method. 这意味着:您需要从提供
start()
方法的类中调用launch(String... args)
start()
方法。
The answers of fabian and James_D provide examples on how to launch JavaFX Applications form within another class. fabian和James_D的答案提供了有关如何在另一个类中启动JavaFX Applications表单的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.