简体   繁体   English

为什么必须从自己的类中启动JavaFx应用程序?

[英]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.Apllicationlaunch(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. fabianJames_D的答案提供了有关如何在另一个类中启动JavaFX Applications表单的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么netty有自己的ConcurrentHashMap? - Why does netty have its own ConcurrentHashMap? 每个类默认都有自己的线程吗? - Does each class have its own Thread by default? 处理已启动的JavaFX应用程序 - Handle on launched JavaFX Application 为什么 Java generics 不允许返回它自己的类型,如果类型是从另一个 class 扩展而来的? - Why does Java generics doesnot allow returning its own type if the type is extended from anotehr class? 使用正在运行的JavaFX应用程序,使用自己独立的控制器类打开一个新窗口 - With a running JavaFX application, open a new window with its own, separate controller class 一个类可以拥有自己类型的字段吗? - Is it okay for a class to have a field of its own type 一个类可以有自己的专用PrintWriter吗? - Can a class have its own private PrintWriter? 为什么此类的每个对象对其成员都具有相同的值? - Why does every object of this class have the same value for its members? java 编译器如何允许 class 拥有自己的类型引用? - How does java compiler allow a class to have its own type reference? 为什么javaFX中的ScheduledService不能作为Task使用具体的类? - Why does the ScheduledService from javaFX not work with a concrete class as Task?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM