2016-09-28 85 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的答案奏效! –

相關問題