繁体   English   中英

JavaFX程序何时调用start方法?

[英]When does a JavaFX program call the start method?

我正在学习JavaFX。 我只能在main方法中看到启动(args)方法。 当我调试进入发布时。 我看不到任何语句调用start()。那么JavaFX程序何时调用start方法? 这是launch(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, true,
                           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);
    }
}

LauncherImpl调用Application#start #start,但是通过PlatformImpl.runAndWait将actuall调用放到JavaFX事件队列中。 这是在Preloader启动后完成的

Application#launch调用LauncherImpl.launchApplication ,它创建一个Thread并调用launchApplication1 ,然后launchApplication通过CountDownLatch等待此Thread终止。

然后,此Thread调用LauncherImpl.launchApplication1 ,如果指定,则启动Preloader ,然后根据有关Preloader调用Application#start runAndWait状态的数字决定,包含在runAndWait调用中,以确保在上下文中调用start 。 JavaFX的GUI /事件队列线程......

这基于Java 8

更新...

LauncherImpl.launcherApplication1调用的theApp.startApplication的实例。

Application通过遍历StackTrace来查找您的类名...所有事情......

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;
    }
}

这将获取您的类的名称,然后使用Class.forName创建一个Class实例并将其传递给LauncherImpl ...

launcherApplication1然后构造此类的新实例并将其分配给引用theApp ,它是Application一个实例

PlatformImpl.runAndWait(new Runnable() {
        @Override public void run() {
            try {
                Constructor<? extends Application> c = appClass.getConstructor();
                app.set(c.newInstance());
                // Set startup parameters
                ParametersImpl.registerParameters(app.get(), new ParametersImpl(args));
                PlatformImpl.setApplicationName(appClass);
            } catch (Throwable t) {
                System.err.println("Exception in Application constructor");
                constructorError = t;
                error = true;
            }
        }
    });
}
final Application theApp = app.get();

然后它继续调用theApp.start ,它调用你的Applicationstart方法....我知道很奇怪,但它是

JavaFX程序既不需要main()方法也不需要调用Application.launch()方法。

您可以从应用程序中删除main()方法, java应用程序启动器将直接调用应用程序上init() (在启动程序线程上)和start() (在JavaFX应用程序线程上)方法。 执行此操作时,将跳过在某些其他线程中讨论的整个LauncherImpl进程(以及通过StackTrace查找启动的类的奇怪决定)。

请参阅相关的Java Enhancement Proposal JEP 153:“增强java命令行启动程序以启动JavaFX应用程序。” 及其随附的问题跟踪链接JDK-8001533“java启动器必须启动javafx应用程序”

当然,如果除了start()方法之外还有main()方法,那么代码将在MadProgrammer的答案中沿着MadProgrammer概述的路径前进。

在编写JavaFX程序时,最好假设从不调用main() (尽管实际上,如果你没有部署为applet,可能会调用main()来阻止人们完全混淆)。

Application javadoc中还描述了此过程:

Java启动程序在JavaFX应用程序线程上加载并初始化指定的Application类。 如果Application类中没有main方法,或者main方法调用Application.launch(),则会在JavaFX Application Thread上构造Application的实例。

在发布时, LauncherImpl的源代码在这里 ,第837行调用start(...)方法。 在源代码中,它非常严峻......

要添加到MadProgrammer的答案:

Application.class ,第241行:

public static void launch(String... args) {
    //...
        if (Application.class.isAssignableFrom(theClass)) {
            Class<? extends Application> appClass = theClass;
            LauncherImpl.launchApplication(appClass, args); // <-- This is where the application is launched

    //...
}

在这里( LauncherImpl.class第118行):

public static void launchApplication(final Class<? extends Application> appClass,
        final String[] args) {
    launchApplication(appClass, savedPreloaderClass, args);
}

在这里(第158行):

public static void launchApplication(final Class<? extends Application> appClass,
        final Class<? extends Preloader> preloaderClass,
        final String[] args) {
    //.......
    Thread launcherThread = new Thread(new Runnable() {
        @Override public void run() {
            try {
                launchApplication1(appClass, preloaderClass, args); // <-- go here
            } catch (RuntimeException rte) {
    //....
}

这是第674行的loooong方法:

private static void launchApplication1(final Class<? extends Application> appClass,
        final Class<? extends Preloader> preloaderClass,
        final String[] args) throws Exception {
    //... Lots of stuff 
    // Eventually, on line 755:
    currentPreloader.start(primaryStage);

    // More things for cases where the previous start() call isn't appropriate
    // Line 773:
    final AtomicReference<Application> app = new AtomicReference<>();
    // Line 790/791:
    Constructor<? extends Application> c = appClass.getConstructor(); // Gets constructor for your class
    app.set(c.newInstance()); // Creates a new instance of your class
    // Line 803:
    final Application theApp = app.get();
    // Line 837:
    theApp.start(primaryStage);
}

因为您的JavaFX项目扩展了ApplicationappClass 应该是JavaFX项目的类对象,因此您定义的start()方法将由theApp.start()调用。

跳过了很多东西,作为源实在太长了被张贴在这里,但是这电话的基本链

也只是学习JavaFx,我的印象是它只是用你的类初始化,因为它是一个高于你的主要参数的方法。 我目前正在使用一个只包含主参数和start方法的简单类,没有其他命令,并且start方法似乎在编译时执行,但是应该调用它

launch(args);

这是我的主要参数的全部内容,这就是为我执行start方法的方法

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM