簡體   English   中英

為什么必須從自己的類中啟動JavaFx應用程序?

[英]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, "");

不必Application子類內部啟動

你可以做

package Freelance;

import javafx.application.Application ;

public class Test
{

    public static void main(String[] args)
    {
        Application.launch(Viewer.class, args);
    }

}

當您查看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);
    }
}

如您所見,foreach循環遍歷堆棧跟蹤。 這意味着:您需要從提供start()方法的類中調用launch(String... args) start()方法。

fabianJames_D的答案提供了有關如何在另一個類中啟動JavaFX Applications表單的示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM