Manual Básico JavaFx
Manual Básico JavaFx
Manual Básico JavaFx
Taller JavaFX
CEP Almería
Índice
1. ¿Qué es JavaFX?..............................................................................................................................2
2. Instalación.........................................................................................................................................3
2.1. Instalación de JDK....................................................................................................................3
2.2. Instalación de Librerías de JavaFX...........................................................................................3
2.3. Instalación de Maven................................................................................................................4
2.4. Instalamos Scene Builder..........................................................................................................5
2.5. Configuración de variables de entorno.....................................................................................5
2.6. Instalación de Eclipse...............................................................................................................8
2.6.1. Plugin para Java FX en eclipse: E(fx)clipse.....................................................................8
2.7. Configuración de Eclipse........................................................................................................10
3. Nuestro primer programa................................................................................................................11
3.1. Agregar Librerías de Java FX.................................................................................................13
3.2. Crear un módulo.....................................................................................................................17
3.3. Clases Principales...................................................................................................................19
3.3.1. Árbol de una aplicación..................................................................................................20
3.4. Ciclo de vida de una aplicación..............................................................................................22
4. Layouts...........................................................................................................................................26
4.1. Hbox........................................................................................................................................26
4.2. FXML y separación vista/controlador....................................................................................28
4.3. Vbox........................................................................................................................................33
4.4. BorderPane..............................................................................................................................36
4.5. FlowPane................................................................................................................................39
4.6. GridPane.................................................................................................................................42
4.5.1. De manera programática.................................................................................................43
4.5.2. Separando la vista en FXML..........................................................................................45
5. Eventos y Listeners.........................................................................................................................46
5.1. Creando eventos SIN controlador...........................................................................................47
5.2. Creando eventos CON controlador (MVC Friendly).............................................................49
6. Threads...........................................................................................................................................51
7. Aplicando estilos con CSS..............................................................................................................56
7.1. Programáticamente con estilos en línea..................................................................................57
7.2. Programáticamente con una hoja de Estilos...........................................................................58
¿Cómo uso la documentación?..................................................................................................61
7.3. Estilos con FXML con SceneBuilder.....................................................................................62
8. Crear un proyecto Maven...............................................................................................................64
9. Demo de aplicación – CalculadoraJavaFX.....................................................................................65
10. Demo de aplicación: Cliente de Gmail.........................................................................................66
1. ¿Qué es JavaFX?
JavaFX es un framework para la creación de GUIs (Graphical User Interfaces) en Java, y es
considerado el sucesor de Swing. Se trata de una API para el diseño de interfaces capaces de correr
en casi cualquier dispositivo con soporte Java.
En Java 8 JavaFX pasó a formar parte de JDK, con lo cual no necesitábamos usar ninguna librería
externa. Sin embargo, desde Java 11, se sacó del JDK, ofreciéndose como un módulo
independiente, entre otras razones por la tendencia de Oracle a dejar en el JDK sólo los
componentes core. Ahora, los módulos de JavaFX están disponibles bien como artefactos maven
para ser usados por Maven/Gradle o como un SDK standalone que debemos incluir en nuestro
proyecto.
La web oficial del proyecto es https://openjfx.io/. Aquí podemos descargarnos el SDK, encontrar los
Javadocs, Getting Starteds, … así como gran cantidad de ejemplos.
Entre las mejoras que incorpora respecto a Swing y AWT tenemos:
• Posibilidad de diseñar la vista usando ficheros XML → XML. Por tanto se produce una
separación efectiva de la vista y el resto de la aplicación.
• Posibilidad de crear aplicaciones siguiendo un patrón MVC.
• Manejo eficiente de hilos de ejecución.
• Facilidad para la creación de gráficos (Charts)
• Facilidad para la creación de gráficos y formas.
• …
5. Como manejar Threads con JavaFX para evitar ocupar el hilo de ejecución principal con
tareas pesadas.
6. Como aplicar estilo CSS a una aplicación
2. Instalación
Instalaremos todo el software necesario en C:/desarrollo.
Descargamos tanto el SDK como los jmods. Recuerda descomprimir ambos en C:/Desarrollo:
Tras esto, haz clic en ‘Variables de entorno… y aparecerá el diálogo de variables de entorno:
En el apartado ‘Variables de sistema’, pulsa en ‘Nueva...’ y añade la variable de nombre
JAVA_HOME y de valor, la ruta donde tengas instalado el jdk. En nuestro caso:
M2_HOME
Para invocar maven desde la terminal, y que otros programas puedan invocarlo automáticamente sin
necesidad de saber su ruta, debemos crear esta variable de sistema.
Seguimos el mismo procedimiento que para JAVA_HOME, pero creamos una con los siguientes
datos:
• Nombre: M2_HOME
• Valor: C:\desarrollo\apache-maven-3.6.2
Sustituye el valor por la ruta de tu instalación de maven.
Tienes que añadir también el directorio bin de maven al Path. Para ello, sigue los mismos pasos
que el apartado anterior (para añadir el directorio bin de java a la variable Path), pero esta vez,
añadiendo a Path:
;C:\desarrollo\apache-maven-3.6.2\bin
Para comprobar que todo ha ido bien, abre una consola y ejecuta los siguientes comandos:
Una vez se abra el diálogo del Marketplace, escribe en el filtro de búsqueda ‘javafx’ y pulsa
buscar. Cuando salgan los resultados, haz clic en el mostrado a continuación:
Nos aseguramos de que tenemos seleccionado el que queremos (Open JDK 13 en nuestro caso). Si
queremos probar con otro, como por ejemplo el de oracle, aquí podemos añadirlo.
Tras esto, selecciona ‘JavaFX Project’ y haz clic en Next. En el siguiente paso, ponle de nombre al
proyecto 01-HolaMundoFX, y selecciona que deseas usar el jdk por defecto:
Pulsa Next dos veces hasta llegar al paso siguiente donde tienes que elegir un nombre para tus
paquetes, en nuestro caso es.juntadeandalucia.holamundofx:
Es debido a que las clases de java FX no son reconocidas por el compilador. Tenemos que incluirlas
en nuestro build path. Para ello, hacemos clic derecho sobre nuestro proyecto en el árbol de
proyectos de la izquierda, y seleccionamos ‘Build Path’ → ‘Configure Build Path ...’:
Pulsa Ok y se cerrará el diálogo. Tras esto, vamos a añadir los jars de javafx a nuestra recién creada
librería Pulsa en el botón ‘Add External JARS’ y localiza los jars de javafx que deberían estar en C:\
desarrollo\javafx-sdk-13.0.1\lib. Añade todos los jars:
Tras esto, vamos aplicando y cerrando diálogos abiertos, hasta que cerramos todos y volvemos al
editor de eclipse. Los errores deberían desaparecer.
module HolaMundoFX {
requires javafx.fxml;
requires javafx.controls;
requires javafx.graphics;
requires javafx.web;
requires javafx.base;
exports es.juntadeandalucia.holamundofx;
}
@Override
public void start(Stage primaryStage) throws Exception {
btn = new Button();
btn.setText("Click me!");
BorderPane pane = new BorderPane();
pane.setCenter(btn);
Esta clase Application tiene una serie de métodos que podemos sobrescribir y que definen el ciclo
de vida de nuestra aplicación, como veremos en el siguiente apartado.
javafx.stage.Stage
Una Stage es, básicamente, una ventana. Representa el marco donde se cargarán luego los layouts y
los controles de una ventana concreta. La clase Application por defecto nos crea una, y nos la
proporciona como parámetro de entrada en su método start.
javafx.scene.Scene
Una escena o Scene, por otro lado, es el conjunto de objetos (controles, layouts, …) que se pintan
en una Stage o Ventana. En resumen, una Stage es el marco de la ventana, que contiene: una barra
de título, botones de maximizar, cerrar y restaurar. Un Scene es un objeto asociado a una Stage, y
cuya función es contener los Nodos. Como nodos en terminología JavaFX se definen los controles
(botones, labels, campos de texto, …) y layouts (elementos para organizar los controles (en tabla,
en vertical, en horizontal, ….).
Podemos hacer el símil con un teatro: el Stage es un escenario, donde se desarrollan Escenas
(Scenes)
de tipo Control. Ej
Node Un botón
de tipo Control. Ej
Node Un botón
de tipo Control. Ej
Node Un botón
Veamos esto con un poco más de detalle. A continuación se muestra lo que se conoce como
SceneGraph o gráfico de escena. Básicamente, toda aplicación JavaFX puede representarse como
un árbol de la siguiente manera:
Stage
Scene
Root
Leaf Leaf
El Stage, es la ventana (marco, con sus botones de cerrar, minimizar, …) , el Scene es la escena
(recuerda el símil Stage = Escenario de un teatro, Scene = una escena que se está representando en
un teatro, con sus actores, su atrezzo, …), y luego tenemos el nodo Root, que es el nodo padre de
todos los nodos que cuelgan de una escena. Este nodo root puede tener hijos ‘hoja’ o ‘leaf’, que son
finales y no tienen más hijos. Y nodos Branch, que pueden tener, a su vez, más hijos ‘Leaf’ y/o
‘Branch’.
Esto se consigue en JavaFX mediante una jerarquía de clases Abstractas.
• La clase base para todos los nodos (sea el root, leaf o branch) es Node
(https://openjfx.io/javadoc/13/javafx.graphics/javafx/scene/Node.html).
• El nodo Root, extiende directamente a la clase abstracta Parent, que en realidad es
extendida por todos los componentes con capacidad de albergar Nodos (que a su vez
extiende a Node) https://openjfx.io/javadoc/13/javafx.graphics/javafx/scene/Parent.html
• A los nodos Leaf u hoja, normalmente se les conoce como controles, porque extienden la
clase base Control. (https://openjfx.io/javadoc/13/javafx.controls/javafx/scene/control/
Control.html)
• Los nodos Branch, también extienden la clase Parent.
1. Método Init
Se ejecuta justo después de ejecutarse el constructor de Application. Se usa para inicializaciones
específicas de la aplicación (leer algún fichero de properties, iniciar alguna conexión, ...), que no
sean relaltivas a GUI (interfaz gráfica)!!!. Esto es debido a que en estos momentos, el Thread que
maneja la interfaz aún no está disponible.
2. Método Start
Se llama cuando el hilo de ejecución de la interfaz gráfica está por fin disponible (creado y listo).
Como puedes ver en el código de nuestra primera aplicación, te proporciona un escenario o Stage
que puedes usar como tu ventana principal.
En este método se cargará todo lo referente a interfaz gráfica: Stages, Scenes, nodos, css, …
3. Método Stop
Cuando la aplicación está a punto de cerrar. Es el sitio ideal para hacer tareas de limpieza como
cierre de conexiones, ficheros, …
En la siguiente modificación de la clase Main.java, hemos sobreescrito los métodos que aún no
teníamos, y hemos modificado el start. En cada uno hemos puesto un
System.out.println(“Estoy en el método X”) para poder observar como
evoluciona una aplicación.
@Override
public void init() throws Exception {
System.out.println(" --- Init --- ");
super.init();
}
@Override
public void stop() throws Exception {
System.out.println(" --- Stop --- ");
super.stop();
}
@Override
public void start(Stage primaryStage) throws Exception {
System.out.println(" --- Start --- ");
btn = new Button();
btn.setText("Click me!");
BorderPane pane = new BorderPane();
pane.setCenter(btn);
4. Layouts
Los layouts son elementos que sirven para organizar Controles (botones, campos de texto, …
incluso otros layouts). Cada uno tiene distintas características que pueden hacerlos más
convenientes según qué situación.
Todos se encuentran en el paquete javafx.scene.layout.
Vamos a darle un repaso rápido a los principales. Para esta sección, vamos a crear un proyecto
llamado 02-DemoLayouts, donde vamos a ir añadiendo una clase java que extiende de Application
para demostrar el uso de cada interfaz, en lugar de crear proyectos separados para cada una.
En el apartado 4.1, pondremos el enlace a un vídeo donde se describe, además de lo relativo al
Hbox, cómo creamos el proyecto inicial.
Todo el código de este apartado, está disponible en:
https://github.com/pes130/02-DemoLayouts
4.1. Hbox
El vídeo guiado de este ejercicio, y de la creación del proyecto, puedes verlo en:
https://youtu.be/89vFhkDAu3w
El Hbox disponen los controles horizontalmente, uno a continuación de otro. En nuestro caso,
vamos a construir esta aplicación:
Usando este layout, los controles se van añadiendo horizontalmente uno a continuación de otro. Sin
intervención por parte del programador.
La parte principal de nuestra clase es la siguiente (recuerda que puedes consultar todo en Github):
@Override
public void start(Stage primaryStage) {
Button btn1 = new Button("Botón 1");
Button btn2 = new Button("Botón 2");
Button btn3 = new Button("Botón 3");
// Cambiar padding
hbox.setPadding(new Insets(10, 20, 10, 20));
// Cambiar margin
HBox.setMargin(btn2, new Insets(30));
Como aspecto destacable, decir que hemos usado 3 métodos de Hbox para definir aspectos gráficos:
• hbox.setSpacing (valor) → introduce un espacio entre los controles dentro del
layout de valor píxeles.
• hbox.setPadding(new Insets (arriba, derecha, abajo,
izquierda)) → Introduce un espacio entre los bordes del layout y su contenido de la
cantidad de píxeles que indiquemos arriba, abajo, derecha y a izquierda. Es
necesario hacerlo a través de este objeto Insets. Hay 4 valores porque sirve para
introducir margin respecto a: 1. al borde superior, 2. al borde derecho, 3. al borde de abajo,
4. al borde izquierdo. Es igual que el padding de CSS.
Para poner el mismo valor en las 4 partes, también podríamos haber usado
hbox.setPadding(new Insets (20))
o bien:
HBox.setMargin(btn2, new Insets(30, 30, 30, 30));
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.HBox?>
En este apartado, hemos tratado de hacer la misma interfaz que en el apartado anterior, con la
salvedad de que en lugar de componer el contenido de la escena en código (en java), hemos
separado la vista de la lógica de la aplicación como primer paso para conseguir una visión MVC
(Modelo Vista Controlador). Se trata de una mejora muy importante que JavaFX introduce respecto
a Swing o AWT.
Para que nuestra aplicación pueda usar este fichero fxml, hemos hecho 2 cosas:
• Hemos creado una carpeta de recursos para alojar ficheros de utilidades, como por
ejemplo, ficheros fxml.
• Hemos puesto, en el método start() de nuestra clase principal, el siguiente código para
cargar el FXML:
FXMLLoader fxml = new FXMLLoader(getClass().getResource("HBox02.fxml"));
Parent hbox = fxml.load();
fichero.fxml
Vista
Aspecto visual
Relación de controles de nuestra ventana
...
Servicio
Controlador
Coordinación entre la vista
y la lógica de negocio
Servicio
Invoca Servicios
Servicio
O desde SceneBuilder:
4.3. Vbox
El comportamiento de Vbox es muy similar al de Hbox, pero organiza los contenidos verticalmente
de manera automática.
En este caso, vamos a construir lo siguiente:
vbox.setPadding(new Insets(20));
vbox.setSpacing(10);
// Alineación
vbox.setAlignment(Pos.CENTER);
Sobre los nuevos controles: Label, TextField y PasswordField, no hay mucho que decir, los
iremos viendo poco a poco conforme aumente la complejidad de los ejemplos.
Por otro lado, JavaFX introduce una colección, ObservableList<E>
(https://openjfx.io/javadoc/13/javafx.base/javafx/collections/ObservableList.html). Se trata de una
colección que implementa las conocidas interfaces de java.util Collection<E> y List<E> entre
otras, y que aporta la ventaja de poder, mediante listeners, observar cambios en los elementos de la
lista para poder asociarles eventos. También veremos más adelante, ejemplos más específicos
acerca de este tipo de listas.
Método setAlignment
Vbox nos permite invocar a este método para especificarle cómo queremos alinear su contenido:
vbox.setAlignment(posicion)
El parámetro posición puede tomar los valores:
• Pos.TOP_LEFT
• Pos.TOP_CENTER
• Pos.TOP_RIGHT
• Pos.CENTER_LEFT
• Pos.CENTER
• Pos.CENTER_RIGHT
• Pos.BOTTOM_LEFT
• Pos.BOTTOM_CENTER
• Pos.BOTTOM_RIGHT
• Pos.BASELINE_LEFT
• Pos.BASELINE_CENTER
• Pos.BASELINE_RIGHT
Por ejemplo, si cambiamos las dimensiones de la escena a 600x600, y ponemos una alineación
CENTER, tenemos:
4.4. BorderPane
BorderPane es un layout que divide la pantalla en 5 zonas, permitiéndonos añadir, de una manera
sencilla, controles y paneles a cada una de estas zonas.
Las áreas en cuestión son:
• Top
• Left
• Center
• Right
• Bottom
En la siguiente figura, podemos ver cómo se distribuyen:
TOP
BOTTOM
//Creación de layouts
HBox hbox_top = new HBox();
hbox_top.setAlignment(Pos.CENTER);
hbox_top.getChildren().addAll(btn_top_1, btn_top_2);
vbox_left.getChildren().addAll(btn_left_1, btn_left_2);
4.5. FlowPane
FlowLayout es muy parecido a Vbox y a Hbox. Organiza los elementos uno a continuación de otro,
de manera horizontal (por defecto), o vertical, según le indiquemos.
Veamos el siguiente ejemplo. Se llama FlowPane05.java:
primaryStage.setScene(scene);
primaryStage.setTitle("FlowPane demo");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
En principio es bastante sencillo. Una cosa destacable, es que si los elementos dispuestos
horizontalmente llegan al borde de la ventana, bajan automáticamente a la siguiente línea (Prueba a
redimensionar la ventana con el ratón):
Por defecto, el FlowPane organiza los elementos horizontalmente, pero podemos cambiar la
organización y ponerlo vertical. El cambio sería este:
...
FlowPane fp = new FlowPane(Orientation.VERTICAL);
fp.getChildren().addAll(btn1, btn2, btn3, btn4, btn5, btn6);
…
El resultado es el siguiente:
fp.setOrientation(Orientation.VERTICAL);
4.6. GridPane
GridPane es un layout que organiza los elementos en forma de tabla. Puede ser útil para ciertas
ventanas como un formulario.
Básicamente, colocamos cada control en el layout indicando su columna y su fila. Imagina que
tenemos una rejilla de 3 x 3, sería algo así:
Los controles que hemos colocado, se están organizando según la siguiente rejilla:
@Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader fxmlLoader = new
FXMLLoader(getClass().getResource("GridLayoutFXML07.fxml"));
Parent gp = fxmlLoader.load();
Scene scene = new Scene(gp);
primaryStage.setTitle("Gridlayout con FXML");
primaryStage.setScene(scene);
primaryStage.show();
}
5. Eventos y Listeners
El proyecto que hemos creado para este apartado, lo tienes en https://github.com/pes130/03-
DemoEventos
Hasta ahora, nos hemos dedicado a la creación de Containers y de Controles, pero no hemos visto
nada sobre controles.
Como siempre, vamos a abordarlo de 2 maneras (aunque recomendando siempre el patrón MVC):
• Creando controles, containers y todo, en Java
• Creando controles y containers en FXML.
En este caso, al no separar la vista en un fichero FXML aparte, no tenemos clase controladora, y por
tanto, creamos los controles y el layout en nuestra clase principal, y los eventos asociados a los
botones también.
Por tanto, todo lo importante de este ejemplo está en ActiionsDemo01.java:
https://github.com/pes130/03-DemoEventos/blob/master/src/es/cursojavafx/demoeventos/
ActionsDemo01.java
Podemos asociar un evento a un control de 2 maneras:
1. Usando una Lambda Expression, disponible desde Java 8. Es la opción más recomendada,
ya que queda un código más simple y contenido.
2. Usando una clase anónima. En programación de eventos es muy típico hacer esto. En este
caso, el evento en sí debe extender la clase abstracta de JavaFX
EventHandler<ActionEvent>. Ya que normalmente, la funcionalidad de un botón no va a ser
reutilizada (y si lo fuera, podríamos encerrarla en un método privado), no tiene mucho
sentido hacer clases con nombre sólo para la funcionalidad de un control, por lo que se suele
optar por una clase abstracta.
Veamos como hacer lo mismo, incrementar el contador al darle al botón btnSumar, de las 2
maneras:
Para aumentar o disminuir el tamaño de la fuente del lblResultado al pasar el ratón por encima,
lo hacemos con los eventos onMouseEntered, y onMouseExited:
lblResultado.setOnMouseEntered(event -> {
lblResultado.setFont(new Font(20));
});
lblResultado.setOnMouseExited(event -> {
lblResultado.setFont(new Font(11));
});
...
<children>
...
@FXML
void incrementarFuente(MouseEvent event) {
this.lblContador.setFont(new Font(30));
}
@FXML
void reestablecerFuente(MouseEvent event) {
this.lblContador.setFont(new Font(11));
}
@FXML
void reiniciarContador(ActionEvent event) {
this.contador = 0;
this.lblContador.setText(String.valueOf(this.contador));
}
Recuerda que, tanto el id de los controles, como el método al que se llamará al producirse algún
evento, se establecen en SceneBuilder en la sección code de cada control:
6. Threads
Existe un hilo de ejecución principal (JavaFX Main Thread) que maneja nuestra GUI, y en el que
se crean todos los nodos y componentes gráficos de nuestra aplicación. Es posible que en nuestra
aplicación necesitemos realizar tareas pesadas que llegen a tardar unos cuantos segundos (consultar
algo en una base de datos, en un servicio rest, algún cálculo pesado como manejo de media, …).
En cualquier caso, hemos de evitar hacer este tipo de tareas en el hilo de ejecución principal de
nuestra aplicación, ya que al hacerlo, la bloqueamos durante el tiempo que dure la tarea, generando
una experiencia de usuario muy mala.
Para evitar esto, JavaFX nos proporciona la clase abstracta Servicio, que nos permite ejecutar tareas
en otro hilo de ejecución diferente al principal, de modo que no bloqueamos la interfaz de usuario.
El vídeo con el paso a paso del ejemplo que vamos a hacer está en https://youtu.be/M2-8jWDU63E
El código fuente completo, lo tienes disponible en:
Vamos a tratar de hacer lo siguiente:
Tenemos 2 botones:
• Invocar servicio: simula hacer una tarea pesada. En realidad, acaba llamando a un
Thread.sleep(3000) para dormir 3 segundos.
• Contador: incrementa un contador cada vez que lo pulsamos
En primer lugar, vamos a hacer las cosas de manera incorrecta. Es decir, vamos a ejecutar esta
supuesta tarea pesada en el hilo de ejecución principal, para ver cómo se bloquea. Y luego, lo
implementaremos en un servicio aparte usando la clase abstracta Service.
@FXML
void invocarServicio(ActionEvent event) {
System.out.println("Comienzo a ejecutar mi servicio");
try {
Thread.sleep(3000);
Random r = new Random();
int resultado = r.nextInt();
this.lblResultado.setText(String.valueOf(resultado));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Termino mi servicio");
}
Clase DemoServicio.java:
@Override
protected Task<Integer> createTask() {
Es decir,
• Mi clase extiende la clase Service<T>, siendo T la clase del resultado que devuelve mi
servicio. En mi caso es un Integer, porque voy a devolver un número entero aleatorio.
(Puede ser una lista de registros de una base de datos, un fichero de vídeo procesado, …)
• La clase Service<T> me obliga a implementar el método Task<Integer>
createTask().
• El método createTask() tiene que devolver una Task<T>, una tarea en la que
debemos obligatoriamente implementar el método call() (Task es otra clase abstracta).
Recuerda que T sigue siendo el tipo a devolver. En mi caso, Integer.
• Es dentro de este call(), donde esperamos 3 segundos y generamos un número aleatorio.
La respuesta no es fácil. Puede hacerse de muchas maneras: Crear un objeto de tipo DemoServicio,
tener un singleton, si usamos SpringBoot, quizás podemos tener un Bean, … nosotros vamos a optar
por algo sencillo: Crear una instancia del objeto DemoServicio.
@FXML
void invocarServicio(ActionEvent event) {
DemoServicio miServicio = new DemoServicio();
miServicio.start();
miServicio.setOnSucceeded(e -> {
Integer resultado = miServicio.getValue();
this.lblResultado.setText(resultado.toString());
});
}
Como ves:
1. Creamos una instancia de nuestro servicio: miServicio.
2. Llamamos al método miServicio.start()
3. Añadimos un manejador de eventos para el evento onSucceeded. Este manejador (hemos
optado por una lambda expression) es una funcionalidad que se ejecutará cuando nuestro
servicio termine e invoque el evento OnSucceeded.
La cosa es que la llamada a un servicio puede lanzar distintos eventos:
De este modo, podemos capturar cuando el momento en el que el servicio esté preparado
(onReady), entre en ejecución (onRunning), falle (onFailed), … y por supuesto, cuando acabe
correctamente: onSucceeded.
Las propiedades son muy parecidas a CSS. En cualquier caso, la referencia completa puedes
encontrarla aquí:
https://openjfx.io/javadoc/13/javafx.graphics/javafx/scene/doc-files/cssref.html
Esta CSS es igual que las de W3C, con la salvedad de que las propiedades suelen cambiar
ligeramente y llevar el prefijo -fx-.
Cada componente lleva ya incorporada una clase (como el class de html, con su nombre en
minúscula). El elemento raíz, lleva la clase .root. De modo que si en la css añadimos:
.root {
-fx-background-color: #111;
-fx-control-inner-background: gray;
-fx-control-inner-background-alt: lightgray;
}
El resultado es:
.label{
-fx-text-fill: #FFF;
}
Tenemos:
Y en la css:
.negrita {
-fx-font-weight: bold;
}
También podemos usar el concepto de id de HTML/CSS, pero para establecer el id, hemos de
ejecutar el método setId. Por ejemplo, si queremos poner el botón btn1 de color verde:
En java:
btn1.setId("btn1");
En css:
#btn1 {
-fx-text-fill: darkgreen;
}
Resultado:
Figura 56:
Usando un id
Para asociar una nueva clase a un nodo, hacemos clic sobre el nodo en cuestión, en nuestro caso el
que tiene el texto ‘Texto normal’, y le asociamos la clase ‘.negrita’:
También podemos asociar un id a un elemento para asociarle un id de css. Con poner la propiedad
Code → fx:id es suficiente: