inheritance javafx javafx-2

inheritance - Iniciar JavaFX desde el método de clase Main que no extiende la aplicación



javafx-2 (3)

Tengo problemas para iniciar una aplicación JavaFX desde un método Main de una clase que no extiende javafx.application.Application

En mi aplicación, existe MainApp.java que debe iniciar el método sobrescrito start() en MainUIController.java , que extiende Applciation

Cuando inicio el método Main desde MainUIController.java todo funciona bien.

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

Después de ejecutar MainApp , aparece el siguiente error:

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


Además de lo que dijo Nejinx, no debe llamar directamente a su start() , siempre llame a launch() , porque configura el entorno JavaFX , incluida la creation of stage y las calls start() pasan la etapa como un parámetro.

Los documentos tienen una nota que indica especialmente esto

NOTA: Este método se llama en el subproceso de aplicación JavaFX

Se puede llamar al launch() desde cualquier clase , teniendo en cuenta si la clase no extiende directamente javafx.application.Application , entonces debe pasar la clase extendiéndola como un argumento para el método de lanzamiento.

Por ejemplo, considere que tiene una clase JavaFXMain que extiende la Application

class JavaFXMain extends Application {...}

Puede usar cualquier otra clase para iniciar la aplicación JavaFX.

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

En su caso, puede probar algo como esto dentro del método principal de MainApp :

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


Debe inicializar el entorno JavaFX, no puede crear un nuevo escenario fuera del lanzamiento (args); ser llamado primero en la clase que extiende la aplicación.


Esto fue muy útil, pero deja la aplicación FX como una aplicación independiente. No puede pasar objetos desde su código que no sea FX y no se le proporciona ningún identificador a la instancia de la Aplicación que se crea.

Se me ocurrió esta solución que no me gusta, pero permite que se pasen los parámetros.

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