Contenidos en Parte 1
- Familiarizándose con JavaFX
- Crear y empezar un proyecto JavaFX
- Uso de Scene builder para diseñar la interfaz de usuario
- Estructura básica de una aplicación mediante el patrón Modelo Vista Controlador (MVC)
Prerequisitos
- Última versión de Java JDK 8 (includes JavaFX 8).
- Eclipse 4.3 o superior con el plugin e(fx)clipse. La forma más sencilla de obtenerlo es descargarse la distribución preconfigurada desde e(fx)clipse website. Como alternativa puedes usar un sitio de actualización para tu instalación de Eclipse.
- Scene Builder 2.0 o superior
Configuración de Eclipse
Hay que indicarle a Eclipse que use JDK 8 y también dónde se encuentra el ejecutable del Scene Builder:
Abre las Preferencias de Eclipse (menú Window | Preferences y navega hasta Java | Installed JREs.
Si no lo tienes el jre1.8 en la lista de JREs, entonces pulsa Add…, selecciona Standard VM y elige el Directorio de instalación (JRE Home directory) de tu JDK 8.
Elimina otros JREs o JDKs de tal manera que JDK 8 se convierta en la opción por defecto.
Navega a Java | Compiler. Establece el nivel de cumplimiento del compilador en 1.8 (Compiler compliance level).
Navega hasta Java | JavaFX. Especifica la ruta al ejecutable del Scene Builder.
Enlaces útiles
Te podría interesar mantener los siguientes enlaces:
- Java 8 API - Documentación (JavaDoc) de las clases estándar de Java
- JavaFX 8 API - Documentación de las clases JavaFX
- ControlsFX API - Documentación para el proyecto ControlsFX, el cual ofrece controles JavaFX adicionales
- Oracle’s JavaFX Tutorials - Tutoriales oficiales de Oracle sobre JavaFX
¡Y ahora, manos a la obra!
Crea un nuevo proyecto JavaFX
En Eclipse (con e(fx)clipse instalado) ve a File | New | Other… y elige JavaFX Project. Especifica el nombre del proyecto (ej. AddressApp) y aprieta Finish.
Borra el paquete application y su contenido si ha sido automáticamente creado.
Crea los paquetes
Desde el principio vamos a seguir buenos principios de diseño de software. Algunos de estos principios se traducen en el uso de la arquitectura denominada Modelo-Vista-Controlador (MVC). Esta arquitectura promueve la división de nuestro código en tres apartados claramente definidos, uno por cada elemento de la arquitectura. En Java esta separación se logra mediante la creación de tres paquetes separados.
En el ratón hacemos clic derecho en la carpeta src, New | Package:
ch.makery.address
- contendrá la mayoría de clases de control ©ch.makery.address.model
- contendrá las clases del modelo (M)ch.makery.address.view
- contendrá las vistas (V)
Nota: Nuestro paquete dedicado a las vistas contendrá también algunos controladores dedicados exclusivamente a una vista. Les llamaremos controladores-vista.
Crea el archivo FXML de diseño
Hay dos formas de crear la interfaz de usuario. Programándolo en Java o mediante un archivo XML. Si buscas en Internet encontrarás información relativa a ambos métodos. Aquí usaremos XML (archivo con la extensión .fxml) para casi todo. Encuentro más claro mantener el controlador y la vista separados entre sí. Además, podemos usar la herramienta de edición visual Scene Builder, la cual nos evita tener que trabajar directamente con el XML.
Haz clic derecho el paquete view y crea un nuevo archivo FXML (New | Other | FXML | New FXML Document) llamado PersonOverview
.
Diseño mediante Scene Builder
Haz clic derecho sobre PersonOverview.fxml
y elige Open with Scene Builder. Ahora deberías ver el Scene Builder con un AnchorPane (visible en la jerarquía de componentes (herramienta Hierarchy) situada a la izquierda).
Selecciona el AnchorPane en tu jerarquía y ajusta el tamaño en el apartado Layout (a la derecha):
Añade un SplitPane (Horizontal Flow) arrastrándolo desde la librería (Library) al área principal de edición. Haz clic derecho sobre el SplitPane en la jerarquía y elige Fit to Parent.
Arrastra un TableView (bajo Controls) al lado izquierdo del SplitPane. Selecciona la TableView (no una sola columna) y establece las siguientes restricciones de apariencia (Layout) para la TableView. Dentro de un AnchorPane siempre se pueden establecer anclajes (anchors) para los cuatro bordes (más información sobre Layouts).
Ve al menú Preview | Show Preview in Window para comprobar si se visualiza correctamente. Intenta cambiar el tamaño de la ventana. La TableView debería ajustar su tamaño al tamaño de la ventana, pues está “anclada” a sus bordes.
Cambia el texto de las columnas (bajo Properties) a “First Name” y “Last Name”.
Selecciona la TableView y elige constrained-resize para la Column Resize Policy (en Properties). Esto asegura que las columnas usarán siempre todo el espacio que tengan disponible.
Añade una Label al lado derecho del SplitPane con el texto “Person Details” (truco: usa la búsqueda en la librería para encontrar el componente Label). Ajusta su apariencia usando anclajes.
Añade un GridPane* al lado derecho, selecciónalo y ajusta su apariencia usando anclajes (superior, derecho e izquierdo).
Añade las siguientes etiquetas (Label) a las celdas del GridPane .
Nota: Para añadir una fila al GridPane selecciona un número de fila existente (se volverá de color amarillo), haz clic derecho sobre el número de fila y elige “Add Row”.
Añade 3 botones a la parte inferior. Truco: Selecciónalos todos, haz click derecho e invoca Wrap In | HBox. Esto los pondrá a los 3 juntos en un HBox. Podrías necesitar establecer un espaciado spacing dentro del HBox. Después, establece también anclajes (derecho e inferior) para que se mantengan en el lugar correcto.
Ahora deberías ver algo parecido a lo siguiente. Usa el menú Preview para comprobar su comportamiento al cambiar el tamaño de la ventana.
Crea la aplicación principal
Necesitamos otro archivo FXML para nuestra vista raíz, la cual contendrá una barra de menús y encapsulará la vista recién creada PersonOverview.fxml
.
Crea otro archivo FXML dentro del paquete view llamado
RootLayout.fxml
. Esta vez, elige BorderPane como elemento raíz..
Abre
RootLayout.fxml
en el Scene Builder.Cambia el tamaño del BorderPane con la propiedad Pref Width establecida en 600 y Pref Height en 400.
Añade una MenuBar en la ranura superior del BorderPane. De momento no vamos a implementar la funcionalidad del menú.
La clase principal en JavaFX
Ahroa necesitamos crear la clase java principal, la cual iniciará nuestra aplicación mediante RootLayout.fxml
y añadirá la vista PersonOverview.fxml
en el centro.
Haz clic derecho en el proyecto y elige New | Other | JavaFX | classes | JavaFX Main Class.
Llama a esta clase
MainApp
y ponla en el paquete de controladoresch.makery.address
(nota: este es el paquete padre de los paquetesview
ymodel
).
La clase generada (MainApp.java
) extiende a la clase Application
y contiene dos métodos. Esta es la estructura básica que necesitamos para ejecutar una Aplicación JavaFX. La parte más importante para nosotros es el método start(Stage primaryStage)
. Este método es invocado automáticamente cuando la aplicación es lanzada desde el método main
.
Como puedes ver, el método start(...)
tomo un Stage
como parámetro. El gráfico siguiente muestra la estructura de cualquier aplicación JavaFX:
Fuente de la imagen: http://www.oracle.com
Es como una obra de teatro: El Stage
(escenario) es el contenedor principal, normalmente una ventana con borde y los típicos botones para maximizar, minimizar o cerrar la ventana. Dentro del Stage
se puede añadir una Scene
(escena), la cual puede cambiarse dinámicamente por otra Scene
. Dentro de un Scene
se añaden los nodos JavaFX, tales como AnchorPane
, TextBox
, etc.
Para tener más información puedes consultar Working with the JavaFX Scene Graph.
Abre el archivo MainApp.java
y reemplaza todo su código con el código siguiente:
package ch.makery.address; import java.io.IOException; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class MainApp extends Application { private Stage primaryStage; private BorderPane rootLayout; @Override public void start(Stage primaryStage) { this.primaryStage = primaryStage; this.primaryStage.setTitle("AddressApp"); initRootLayout(); showPersonOverview(); } /** * Initializes the root layout. */ public void initRootLayout() { try { // Load root layout from fxml file. FXMLLoader loader = new FXMLLoader(); loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml")); rootLayout = (BorderPane) loader.load(); // Show the scene containing the root layout. Scene scene = new Scene(rootLayout); primaryStage.setScene(scene); primaryStage.show(); } catch (IOException e) { e.printStackTrace(); } } /** * Shows the person overview inside the root layout. */ public void showPersonOverview() { try { // Load person overview. FXMLLoader loader = new FXMLLoader(); loader.setLocation(MainApp.class.getResource("view/PersonOverview.fxml")); AnchorPane personOverview = (AnchorPane) loader.load(); // Set person overview into the center of root layout. rootLayout.setCenter(personOverview); } catch (IOException e) { e.printStackTrace(); } } /** * Returns the main stage. * @return */ public Stage getPrimaryStage() { return primaryStage; } public static void main(String[] args) { launch(args); } }
Los diferentes comentarios deben darte pistas sobre lo que hace cada parte del código.
Si ejecutas la aplicación ahjora, verás ago parecido a la captura de pantalla incluida al principio de este artículo.
Problemas frecuentes
Si JavaFX no encuentra un archivo fxml
puedes obtener el siguiente mensaje de error
java.lang.IllegalStateException: Location is not set.
Para resolverlo comprueba otra vez que no hayas escrito mal el nombre de tus archivos fxml
.
¿Qué es lo siguiente?
En Tutorial Parte 2 añadiremos algunos datos y funcionalidad a nuestra aplicación de contactos.