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