tutorial - manejo de ventanas javafx
¿Puedo generar automáticamente clases de controlador desde FXML? (4)
Tal como lo entiendo, al usar FXML para describir una escena de Java FX , la clase del controlador se escribe manualmente y sus variables y métodos miembros pueden referenciarse desde el archivo .fxml
. Al cargar la escena con el FXMLLoader
, las variables miembro se configuran en los elementos de escena correspondientes y los métodos se conectan automáticamente a los eventos correspondientes. Esto funciona, pero es muy engorroso ya que los cambios deben realizarse en dos lugares y los errores solo se mostrarán en el tiempo de ejecución.
He visto otros marcos de GUI que le permiten generar el controlador a partir de una descripción de escena como una clase abstracta que debe implementarse para acceder a los elementos de escena y manejar los eventos. Un ejemplo de lo que quiero decir:
Yo crearía el siguiente archivo .fxml
(por ejemplo, usando el JavaFX Scene Builder ):
<AnchorPane ... >
<children>
<Button fx:id="button" ... text="Button" onAction="#buttonPressed" />
</children>
</AnchorPane>
En algún lugar de mi proceso de compilación, se .java
el siguiente archivo .java
(por ejemplo, usando un plugin Maven ):
abstract class TestController {
protected final Parent root;
protected final Button button;
{
// Load test.fxml file
// Assign scene elements to root and button
// Attach event handler to the button that calls buttonClicked()
}
protected abstract void buttonClicked(ActionEvent event);
}
Podría entonces, posiblemente varias veces, crear una implementación concreta de ese controlador:
final class TestControllerImpl extends TestController {
TestControllerImpl(String buttonLabel) {
button.setText(buttonLabel);
}
@Override
protected void buttonClicked(ActionEvent event) {
button.setText("I''ve been clicked! What a great day!");
}
}
¿Hay algún proyecto con el objetivo de hacer esto? ¿O hay un problema con este enfoque aplicado a FXML ?
Veo los siguientes beneficios de este enfoque:
- Las declaraciones de variables miembro y métodos para el controlador se generan automáticamente.
- Todas las variables de miembro son finales y están protegidas en lugar de no finales y son públicas o anotadas.
- Lo mismo para los métodos, están protegidos en lugar de públicos o anotados.
- No implementar un método o escribir mal su nombre dará lugar a un error del compilador.
- La configuración programática de la escena se puede hacer en el constructor en lugar de en un método
initialize()
porque el constructor se ejecutará después de que la escena se haya cargado y sus elementos se hayan asignado a las variables miembro.
@Feuermurmel
no, no hay ninguna forma de generar automáticamente la clase de controlador para el archivo particula .fxml.
debe definir dinámicamente declarar la variable y el método con la anotación @fxml y establecer (vincular) en Scence Builder.
No hay nada que yo sepa que haga exactamente lo que propones en tu pregunta.
Probablemente esta respuesta probablemente terminará bastante obsoleta con el tiempo.
Tecnologías Alternativas
JRuby logra la mayoría de los beneficios descritos utilizando un enfoque ligeramente diferente: utiliza la magia de programación dinámica de jRuby para crear automáticamente miembros de la clase Ruby desde el FXML dinámicamente en tiempo de ejecución.
Tom Schindl escribió una herramienta que genera código de Java de FXML. De los enfoques enumerados en esta respuesta, la herramienta de Tom parece más cercana a su pregunta.
SceneBuilder Skeletons
Un generador de código Java similar de FXML está disponible en SceneBuilder View | Show Sample Controller Skeleton
View | Show Sample Controller Skeleton
característica View | Show Sample Controller Skeleton
, que se describe en esta publicación de blog . Cuando uso SceneBuilder, uso esta función todo el tiempo y trato de mantener mis controladores muy livianos para que casi todos sean códigos autogenerados de la función del esqueleto de SceneBuilder.
Sin embargo, es un poco molesto porque no logra una separación limpia del código generado del código escrito a mano, por lo que debe tener cuidado cuando realiza actualizaciones en el FXML y desea generar un nuevo esqueleto y copiarlo y pegarlo en partes de su Controlador existente (además de que es una operación manual ligeramente propensa a errores que requiere un poco de tiempo de desarrollador).
El código fuente de SceneBuilder está disponible si desea ver cómo funciona.
Potenciales complementos de herramientas de compilación
Dicha característica de generación de código podría ser una valiosa adición a algunas de las herramientas de compilación existentes en el ecosistema JavaFX, como el plugin JavaFX Maven o el plugin JavaFX Gradle (o un plugin separado por derecho propio).
Desarrollo futuro
Creo que Oracle también está trabajando en una extensión de funciones para FXML para una futura versión de JavaFX (posterior a Java 8) que compila FXML directamente en el código de bytes de Java (archivos de clase), pasando por alto el paso del código fuente de Java. Este tipo de característica probablemente lograría la mayoría de sus beneficios detallados.
Esto ahora es compatible con SceneBuilder, NetBeans y Eclipse. Tenga en cuenta que esto funciona de la caja en NetBeans y SceneBuilder, pero en Eclipse primero necesita el plugin e (fx) clipse.
SceneBuilder: con un archivo FXML abierto en el editor, ingrese el menú para seleccionar "Ver" y "Mostrar esqueleto del controlador de muestra".
Eclipse: abra el archivo fxml para que los contenidos se muestren en el panel de edición de código (debería ver el fxml como texto plano xml con resaltado de sintaxis dentro de Eclipse, no representado visualmente en SceneBuilder). Haga clic derecho en el código en Eclipse y seleccione "Código" y luego "Generar controlador".
NetBeans: en NetBeans es incluso más fácil, haga clic derecho en el archivo fxml en el explorador de proyectos y seleccione "Make Controller".
Es posible con la versión 8 de NetBeans.
Abra FXML, vaya a Fuente y haga clic en generar controlador.
Editar: Ahora se puede hacer en cualquier IDE, Eclipse necesita un plugin pensado.