viernes, 4 de diciembre de 2015

Hola Mundo con JavaFX: Stage, Scene, Node y Scene Graph

En este artículo vamos a crear nuestro primer programa utilizando Java Fx 8, veremos su estructura y analizaremos las distintas partes de las que se compone.

Cuando creamos un nuevo proyecto tenemos disponibles varias alternativas para iniciarlo:
Nuevo Proyecto JavaFX
Nuevo Proyecto en JavaFX

Básicamente son plantillas para evitarnos escribir código o crear nuevos archivos. La opción de JavaFX Application es la opción base, pero resultan más interesantes las siguientes, como Preloader que se utiliza para mostrar una pantalla inicial con alguna información, por ejemplo si debe cargar datos o realizar acciones que pueden demorarse se mostraría una ventana de con una barra de progreso, lo que mejora mucho la experiencia de usuario, ya que ejecutar un programa y esperar unos segundos a que se inicie sin saber que está pasando suele disgustarnos a todos.


Por otro lado la opción de FXML Application que es la opción que vamos a utilizar es la forma de utilizar JavaFx más interesante. Se basa en el patrón Modelo Vista Controlador, por lo que tendremos un archivo XML o FXML en el que indicaremos la disposición de los controles como botones, cajas de texto étc y también tendremos la clase controladora, que se encargará de los eventos, es decir que sucede cuando el usuario pulsa el botón.
A todo esto hay que añadir que el diseño de las ventanas se realiza con Scene Builder lo que nos facilitará enormemente el trabajo y nos ahorra escribir código XML.

Voy a crear un proyecto llamado HolaJavaFX:





Por defecto se crean los archivos:






HolaJavaFX.java


Es nuestra clase principal y el punto de entrada a la aplicación.

package holajavafx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class HolaJavaFX extends Application {
    
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        
        Scene scene = new Scene(root);
        
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
    
}

En este simple código vemos varios puntos importantes, y el primero de ellos es que nuestra clase principal extiende de la clase Application. Por otro lado el método main no es necesario y lo podemos borrar sin mayor problema, ya que nuestra aplicación realmente se inicia en el método start.
El método start es el que contiene nuestro primer código en Java FX, pero para entenderlo es necesario aclarar los conceptos de Stage, Scene, Node y Scene Graph.

STAGE Y SCENE

Uno de los símiles que más se aproxima para entender estos conceptos es ver el stage como un escenario, teatro o cine, en el cual, se desarrollan escenas. Dicho de otro modo, stage es un espacio y una escena define que sucede en ese espacio.
Visto así, tenemos que un stage es el contenedor de nivel superior, que como mínimo consta de una escena, que a su vez es contenedora de otros elementos.
Si nuestra programa es una aplicación de escritorio, el stage será la ventana, con su barra de título, y botones de maximizar, minimizar o cerrar, en el caso que que se ejecutase en un navegador web como Chrome, nuestro stage esta embebido dentro del navegador.

NODOS y SCENE GRAPH

Los nodos son elementos individuales que forman una escena, como por ejemplo botones, cuadros de texto, layouts etc. Si seguimos con el símil de un teatro, los nodos serían los actores y el atrezo.
Sin embargo, en Java FX los nodos pueden tener nodos hijos, que a su vez tienen otros nodos hijos, como si de las ramas de un árbol se tratase.
El conjunto de todos los nodos que forman una escena es lo que llamamos Scene Graph o grafo de la escena.
En Java FX existe un nodo especial llamado root node o nodo raíz/padre del cual extienden todos los demás nodos, y es el único que no tiene un nodo padre, por que todos los demás nodos si lo tienen y son descendientes ya sea directa o indirectamente del root node.
Todos los nodos extienden de la clase Node, y existen otras clases que extienden directa o indirectamente de Node, como Parent, de la cual ya tenemos un objeto en nuestra platilla por defecto, y por nombrar algunas más tenemos Group, Region o Control

Una vez entendidos los conceptos, en nuestra clase principal HolaJavaFX.java como puedes observar lo primero que hacemos es cargar todos los nodos hijos, en el root node, después creamos una escena y añadimos la escena a nuestro stage, por último mostramos con el método .show() nuestro stage.
Con estas 4 líneas de código, ya podemos realizar el diseño en el FXMLDocument.fxml y programar las acciones en el FXMLDocumentController.java.



FXMLDocument.fxml



Este es un archivo XML, que contiene el diseño de nuestra ventana, si observas el código en netbeans veras que contiene parámetros y propiedades indicando el tamaño y posición, pero además de eso realiza la estructura de nodos padre-hijo.
Voy a destacar los siguientes fragmentos de código: 

fx:controller="holajavafx.FXMLDocumentController"

que indica cual va a ser nuestra clase Java que controle las acciones de los nodos.

Si has instalado Scene Builder como indico en Introducción a JavaFX - Herramientas Necesarias al hacer doble click sobre el archivo en Netbeans, se abrirá un GUI para editar este archivo de forma más visual.
Scene Builder para Java FX


FXMLDocumentController.java


Esta es la clase controladora de los eventos de entrada del ratón y teclado:

package holajavafx;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;

public class FXMLDocumentController implements Initializable {
    
    @FXML
    private Label label;
    
    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
        label.setText("Hello World!");
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    
    
}

Observa como se utilizan anotaciones @FXML para elementos que tenemos en nuestro archivo FXMLDocument.fxml y se pueden generar automáticamente con Scene Builder.


Puedes ejecutar la aplicación y verás una pantalla similar a esta una vez pulsado el botón. 
En mi caso concreto, al utilizar Linux Mint, toma por defecto el tema de mi escritorio, si lanzase la aplicación en Windows o Mac OS, cambiaría el aspecto automáticamente. Obviamente esto es facilmente modificable, por ejemplo mediante CSS, que es una de entre otras muchas características de Java FX



No hay comentarios:

Publicar un comentario