2016-09-28 40 views
1

我试了下面的代码,并被迫启动我的JavaFx应用程序Viewer而不直接调用方法launch为什么JavaFx应用程序必须从它自己的类中启动?

这里是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

这些文档相当有用,它描述了使用'launch()'方法的正确方法。选中[此处](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Application。html) – AntJavaDev

+1

顺便说一下,您应该将'args'传递给'launch'方法,而不是空字符串或空数组。 JavaFX将使它们在[应用程序参数](http://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html#getParameters--)中可用。 – VGR

回答

1

,你会发现这个代码堆栈跟踪。这意味着:您需要从提供start()方法的课程中调用launch(String... args)方法。

fabianJames_D提供关于如何启动的JavaFX应用实例的答案形成另一个类中。

+0

谢谢。这是很好的细节。 –

6

由于launch是一个静态方法中,应用类不能由除检查堆栈其他手段,因为编译后

Application.launch(""); 

作为

Viewer.launch(""); 

结束相同的字节码来确定,只有在堆栈中的某处找到Application类时,检查堆栈才有效,这就是为什么launch需要从Application类中调用的原因。

然而有一种替代方案:
您可以在Application类传递给the overloaded version of the launch method

Application.launch(Viewer.class, ""); 
+0

我明白了。下面的@ Turing85的细节现在可以理解了。 –

4

It doesn't必须从Application子内推出。在

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循环迭代:

当你看看javafx.application.Apllication的实施launch(String... args)你可以做

package Freelance; 

import javafx.application.Application ; 

public class Test 
{ 

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

} 
+0

谢谢。你和Fabian的答案奏效! –

相关问题