2014-09-02 17 views
11

sto avendo problemi di avviare un'applicazione JavaFX da un metodo principale di una classe che non si estende javafx.application.Applicationpartire JavaFX dal metodo Main di classe che non si estende Application

Nella mia applicazione c'è la MainApp.java che dovrebbe iniziare il metodo sovresposta start() nel MainUIController.java, che si estende Applciation

Quando avvio il metodo principale dal MainUIController.java tutto funziona bene.

MainApp.java

public class MainApp { 

    public static void main(String[] args) { 
     PersonJDBCTemplate jdbc = connect(); 
     MainUIController mUIc = new MainUIController(jdbc); 
     mUIc.start(new Stage()); 

    } 

    public static PersonJDBCTemplate connect() { 
     ApplicationContext context = new ClassPathXmlApplicationContext(
       "Beans.xml"); 
     PersonJDBCTemplate personJDBCTemplate = (PersonJDBCTemplate) context 
       .getBean("personJDBCTemplate"); 
     return personJDBCTemplate; 
    } 
} 

MainUIController.java

public class MainUIController extends Application { 

    private Stage stage; 
    // private User loggedUser; 
    private final double MINIMUM_WINDOW_WIDTH = 800.0; 
    private final double MINIMUM_WINDOW_HEIGHT = 570.0; 
    private String version = "0.6"; 
    private PersonJDBCTemplate jdbc; 

    public MainUIController(PersonJDBCTemplate jdbc) { 
     this.jdbc = jdbc; 

    } 

    @Override 
    public void start(Stage primaryStage) { 
     try { 
      stage = primaryStage; 
      stage.setTitle("Sharp"); 
      stage.setMinWidth(MINIMUM_WINDOW_WIDTH); 
      stage.setMinHeight(MINIMUM_WINDOW_HEIGHT); 
      stage.setResizable(false); 
      gotoLogin(); 
      primaryStage.show(); 
     } catch (Exception ex) { 
      Logger.getLogger(MainUIController.class.getName()).log(
        Level.SEVERE, null, ex); 
     } 
    } 

    public void gotoLogin() { 
     try { 
      LoginController login = (LoginController) replaceSceneContent("/fxml/Login.fxml"); 
      login.setApp(this); 
     } catch (Exception ex) { 
      Logger.getLogger(MainUIController.class.getName()).log(
        Level.SEVERE, null, ex); 
     } 
    } 
} 

Dopo aver eseguito il MainApp, ottengo il seguente errore:

Exception in thread "main" java.lang.ExceptionInInitializerError 
at javafx.stage.Window.<init>(Window.java:1110) 
at javafx.stage.Stage.<init>(Stage.java:236) 
at javafx.stage.Stage.<init>(Stage.java:224) 
at ch.kit.sharp.main.MainApp.main(MainApp.java:15) 
Caused by: java.lang.IllegalStateException: This operation is permitted on the event thread only; currentThread = main 
at com.sun.glass.ui.Application.checkEventThread(Application.java:445) 
at com.sun.glass.ui.Screen.setEventHandler(Screen.java:245) 
at com.sun.javafx.tk.quantum.QuantumToolkit.setScreenConfigurationListener(QuantumToolkit.java:600) 
at javafx.stage.Screen.<clinit>(Screen.java:80) 
... 4 more 

risposta

19

In aggiunta a quanto detto Nejinx, non è necessario chiamare direttamente il vostro start(), sempre chiamare launch(), perché si imposta l'JavaFX ambiente, tra cui creation of stage e calls start() passando il palco come un parametro ad esso.

The docs ha una nota speciale che indica questo

NOTA: Questo metodo viene chiamato sul thread JavaFX Application

Il launch() possono essere richiamati dalla qualsiasi classe, prendendo in considerazione se il la classe non sta estendendo direttamente javafx.application.Application, quindi è necessario passare la classe estendendola come argomento al metodo di lancio.

Ad esempio, si consideri di avere una classe JavaFXMain che si estende Application

class JavaFXMain extends Application {...} 

è possibile utilizzare qualsiasi altra classe, per avviare l'applicazione JavaFX.

class Main { 
    ... 
    public void someMethod() { 
     ... 
     JavaFXMain.launch(JavaFXMain.class); // Launch the JavaFX application 
     ... 
    } 
} 

Nel tuo caso, si può provare qualcosa di simile all'interno del principale metodo di MainApp:

// You may remove args if you don't intend to pass any arguments 
MainUIController.launch(MainUIController.class, args) 
2

È necessario inizializzare l'ambiente JavaFX, non è possibile creare una nuova fase all'esterno di avvio (args); essere chiamato prima sulla classe che estende l'applicazione.

0

Questo è stato molto utile, ma lascia l'applicazione FX come applicazione stand alone. Non puoi passare oggetti dal tuo codice non FX e non ti viene fornito alcun handle per l'istanza dell'applicazione che viene creata.

Mi sono inventato questa soluzione che non mi fa impazzire ma che consente di passare i parametri.

package hacks; 

import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

/** 
* Created by WorkDay on 8/11/16.<br> 
* <br> 
* HelloWorld is a javaFX app that needs parameters that are real objects 
*/ 

class AppParameterLauncher { 
    public static void main(String[] args) { 
     HelloWorld.launch(new ObjectThatContainsData("brave"), new ObjectThatContainsData("new")); 
    } 
} 


public class HelloWorld extends Application { 

    private static ObjectThatContainsData staticData1 = null; 
    private static ObjectThatContainsData staticData2 = null; 


    public static void launch(ObjectThatContainsData data1, ObjectThatContainsData data2) { 
     HelloWorld.staticData1 = data1; 
     HelloWorld.staticData2 = data2; 
     Application.launch(HelloWorld.class); 
    } 

    private final ObjectThatContainsData data1 = HelloWorld.staticData1; 
    private final ObjectThatContainsData data2 = HelloWorld.staticData2; 

    @Override 
    public void start(Stage primaryStage) { 

     String Text = "Hello "+data1+" "+data2+" World!"; 
     primaryStage.setTitle(Text); 
     Button btn = new Button(); 
     btn.setText("Say '"+Text+"'"); 
     btn.setOnAction(new EventHandler<ActionEvent>() { 

      @Override 
      public void handle(ActionEvent event) { 
       System.out.println("Hello World!"); 
      } 
     }); 

     StackPane root = new StackPane(); 
     root.getChildren().add(btn); 
     primaryStage.setScene(new Scene(root, 300, 250)); 
     primaryStage.setX(0); 
     primaryStage.setY(0); 
     primaryStage.show(); 
    } 
} 

class ObjectThatContainsData { 
    public final String data; 

    ObjectThatContainsData(String data) { 
     this.data = data; 
    } 

    @Override 
    public String toString() { 
     return data; 
    } 
} 
Problemi correlati