Enfoque recomendado
Esta respuesta enumera diferentes mecanismos para pasar parámetros a los controladores FXML.
Para aplicaciones pequeñas, recomiendo pasar parámetros directamente de la persona que llama al controlador: es simple, directo y no requiere marcos adicionales.
Para aplicaciones más grandes y complicadas, valdría la pena investigar si desea utilizar mecanismos de inyección de dependencia o bus de eventos dentro de su aplicación.
Pasando parámetros directamente de la persona que llama al controlador
Pase datos personalizados a un controlador FXML recuperando el controlador de la instancia del cargador FXML y llamando a un método en el controlador para inicializarlo con los valores de datos requeridos.
Algo así como el siguiente código:
public Stage showCustomerDialog(Customer customer) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
Stage stage = new Stage(StageStyle.DECORATED);
stage.setScene(
new Scene(
(Pane) loader.load()
)
);
CustomerDialogController controller =
loader.<CustomerDialogController>getController();
controller.initData(customer);
stage.show();
return stage;
}
...
class CustomerDialogController {
@FXML private Label customerName;
void initialize() {}
void initData(Customer customer) {
customerName.setText(customer.getName());
}
}
Se construye un nuevo FXMLLoader como se muestra en el código de ejemplo, es decir new FXMLLoader(location)
. La ubicación es una URL y puede generar dicha URL a partir de un recurso FXML al:
new FXMLLoader(getClass().getResource("sample.fxml"));
Tenga cuidado de NO usar una función de carga estática en el FXMLLoader, o no podrá obtener su controlador desde la instancia del cargador.
Las instancias de FXMLLoader nunca saben nada sobre los objetos de dominio. No pasa directamente objetos de dominio específicos de la aplicación al constructor FXMLLoader, sino que:
- Construya un FXMLLoader basado en el marcado fxml en una ubicación específica
- Obtenga un controlador de la instancia FXMLLoader.
- Invoque métodos en el controlador recuperado para proporcionar al controlador referencias a los objetos de dominio.
Este blog (de otro escritor) proporciona un ejemplo alternativo, pero similar .
Configuración de un controlador en el FXMLLoader
CustomerDialogController dialogController =
new CustomerDialogController(param1, param2);
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
loader.setController(dialogController);
Pane mainPane = (Pane) loader.load();
Puede construir un nuevo controlador en código, pasando los parámetros que desee de su llamante al constructor del controlador. Una vez que haya construido un controlador, puede configurarlo en una instancia de FXMLLoader antes de invocar la load()
instancia método de .
Para configurar un controlador en un cargador (en JavaFX 2.x) NO PUEDE definir un fx:controller
atributo en su archivo fxml.
Debido a la limitación en la fx:controller
definición en FXML, personalmente prefiero obtener el controlador del FXMLLoader en lugar de configurar el controlador en el FXMLLoader.
Hacer que el controlador recupere los parámetros de un método estático externo
Este método se ejemplifica con la respuesta de Sergey a Javafx 2.0 How-to Application.getParameters () en un archivo Controller.java .
Usar inyección de dependencia
FXMLLoader admite sistemas de inyección de dependencias como Guice, Spring o Java EE CDI al permitirle configurar una fábrica de controladores personalizados en FXMLLoader. Esto proporciona una devolución de llamada que puede usar para crear la instancia del controlador con valores dependientes inyectados por el sistema de inyección de dependencia respectivo.
Un ejemplo de aplicación JavaFX y la inyección de dependencia del controlador con Spring se proporciona en la respuesta a:
Un marco de inyección de dependencia realmente agradable y limpio se ejemplifica en el marco afterburner.fx con una aplicación de muestra de ataques de aire que lo utiliza. afterburner.fx se basa en JEE6 javax.inject para realizar la inyección de dependencia.
Use un bus de eventos
Greg Brown, el creador e implementador de la especificación FXML original, a menudo sugiere considerar el uso de un bus de eventos, como el EventBus de Guava , para la comunicación entre controladores instanciados FXML y otra lógica de aplicación.
EventBus es una API de publicación / suscripción simple pero potente con anotaciones que permite a los POJO comunicarse entre sí en cualquier lugar de una JVM sin tener que referirse entre sí.
Preguntas y respuestas de seguimiento
en el primer método, ¿por qué regresas a Stage? El método también puede anularse porque ya está dando el comando show (); justo antes de la etapa de regreso; ¿Cómo se planifica el uso devolviendo el escenario?
Es una solución funcional a un problema. Se devuelve una etapa de la showCustomerDialog
función para que una clase externa pueda almacenar una referencia a ella que tal vez desee hacer algo, como ocultar la etapa con un clic de botón en la ventana principal, más adelante. Una solución alternativa orientada a objetos podría encapsular la funcionalidad y la referencia de etapa dentro de un objeto CustomerDialog o hacer que CustomerDialog extienda Stage. Un ejemplo completo de una interfaz orientada a objetos para un cuadro de diálogo personalizado que encapsula FXML, el controlador y los datos del modelo está más allá del alcance de esta respuesta, pero puede ser una publicación de blog que valga la pena para cualquiera que esté dispuesto a crear una.
Información adicional proporcionada por el usuario de StackOverflow llamado @dzim
Ejemplo de inyección de dependencia de arranque de resorte
La pregunta de cómo hacerlo "The Spring Boot Way", hubo una discusión sobre JavaFX 2, que respondí en el enlace permanente adjunto. El enfoque aún es válido y se probó en marzo de 2016, en Spring Boot v1.3.3. PUBLICACIÓN:
https://stackoverflow.com/a/36310391/1281217
A veces, es posible que desee pasar los resultados a la persona que llama, en cuyo caso puede consultar la respuesta a la pregunta relacionada: