Entrada destacada
Barra de menu con estilo en JavaFX utilizando CSS
- Obtener enlace
- X
- Correo electrónico
- Otras aplicaciones
Barra de menu con estilo en JavaFX utilizando CSS
En esta entrada quiero compartir un poco más sobre JavaFx. En estos últimos días he estado trasteando un poco con las interfaces graficas de java sobre todo con la librería JavaFx y bueno, para ser sincero me sentía acostumbrado a trabajar con Swing, sin embargo, como sabrás esta librería ya se encuentra casi en desuso y sobre todo con las nuevas tendencias en diseño pues se vuelve complicado poder darles a nuestros proyectos un estilo moderno.
En esta ocasión he decido
compartir un poco de lo que he aprendido.
Vamos a darle estilo o una
barra de menús, dándole un diseño mas acorde a nuestras necesidades, empezaré
creando un nuevo proyecto, en mi caso lo haré utilizando el IntelliJ, tu puedes
hacerlo en el IDE que más te agrade.
El proyecto lo cree
utilizando Maven y correrá con un JDK 11, también y la versión 18.0.1 de
JavaFx.
Las dependencias en mi
archivo POM quedan de la siguiente forma
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>18.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>18.0.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
Como es de esperar nuestro
IDE genera automáticamente un código de prueba, con un archivo FXML y su controlador
correspondiente. Para trabajar la parte grafica utilizaré SceneBuilder.
Bueno pare realizar el test
de cambiar el diseño empecé renombrando el archivo FXML por MenuBarTest.fxml y
también la clase principal a la cual llamé Main.java y el controlador
correspondiente le coloqué MenuBarTestController.java.
En mi diseño simplemente
agregué como nodo padre un BorderPane y en la sección TOP de este coloqué una
MenuBar. Al agregar el nodo al BorderPane, SceneBuilder tres menús (File, Edit,
Help) los cuales contienen a su vez MenuItems, esto me va muy bien para esta
practica ya que la idea es darle estilo tanto a la MenuBar como a los Menus y
los MenuItems.
El siguiente paso que
realicé es crear un nuevo archivo CSS y guardarlo en la carpeta resources, para
esta prueba lo guardaré en el mismo directorio en donde se encuentra el archivo
FXML.
En la imagen anterior se
puede observar la estructura del proyecto de prueba, claro está que de acuerdo
al IDE que utilicemos puede variar o no la misma.
El siguiente paso es
indicarle a nuestro archivo FXML que debe de importar y utilizar el archivo
CSS, en JavaFX cada uno de los nodos puede importar su propio archivo css, en
esta ocasión le asigne a la barra de menú el archivo CSS que utilizaré para darle
estilo, por lo que en SceneBuilder es sencillo, simplemente hay que pinchar el
botón de Stilesheets como se observa en la siguiente imagen:
Luego nos movemos en el buscador
de archivos hasta donde se encuentra nuestro archivo CSS si es que no se tiene
como en mi caso en el mismo directorio de nuestro archivo FXML. Una vez
seleccionado nuestro archivo y pinchando en el botón de aceptar veremos que
ahora nos muestra un cambio en la zona de Stilesheets como se muestra en la
siguiente imagen:
Ya con esto podemos hacer
uso de nuestro archivo CSS, por lo que comenzare dándole estilo a la barra de
menú.
A continuación, les muestro
el código CSS comentado.
/*
Para acceder a la menubar utilizamod la clase css menu-bar.
Nota: en css de javafx hay muchas de las funciones del css
para el desarrollo web que no son aplicables.
*/
.menu-bar{
/*Le damos un background color de verde azulado*/
-fx-background-color: #00796B;
/*Le damos un padding de 5 */
-fx-padding: 5;
}
El resultado del código
anterior lo podemos observar en la siguiente imagen:
El color de la barra de
menú cambio a verde azulado, ahora para darle un poco mas de estilo al diseño
cambiare el tipo de fuente, color del texto de los Label y también usare la tipografía
Roboto, así mismo le daré un tamaño de fuente de 18.
/*
Para acceder al Label que muestra el texto del Menu entonces lo hacemos de la siguiente forma
.menu-bar > .container > . menu-button > .label
de esta forma podemos cambiar el color, tamaño tipo de fuente, padding entre otras funciones
cabe destacar que utilizando esta forma cambiaremos solamente los Label que se encuentran
dentro de la barra de menus ya que si solo utilizamos la clase .label el codigo css afectaría
a todos los Labels que contenga nuestro border pane
para esta prueba le cambiaré el color de texto, el tamaño de la fuente el tipo de fuente y el
tipo de letra
*/
.menu-bar > .container > .menu-button >.label{
/*Cambiamos el color del texto*/
-fx-text-fill: #FFFFFF;
/*Cambiamos el tamaño de la fuente*/
-fx-font-size: 18;
/*Cambiamos el tipo de fuente Nota: en mi caso utilizo la fuente roboto porque la tengo
instalada dentro de mi sistema operativo*/
-fx-font-family: "Roboto";
/*Colocamos el texto en negrita*/
-fx-font-weight: bold;
}
El resultado del código
anterior lo podemos observar en la siguiente imagen:
Como podemos observar se ve
mucho mejor, ahora bien, para darle al estilo al menú cuando el ratón se coloca
sobre el, utilizamos la pseudoclase hover el cual también podemos complementar
con la pseudo clase showing y focused.
La pseudoclase showing
controla cuando el menú ha sido pinchado y muestra los Menu Items que tiene
como hijos, como podemos observar en las siguientes imagenes:
Pseudoclase hover:
Pseudoclase showing:
El comportamiento de la
pseudoclase focused la veremos cuando le demos estilo al menú item. Para darle
estilo a estos comportamientos podemos utilizar el siguiente código:
/*
Cuando el cursor del raton se encuentra sobre el menu cambiamos el color a negro pero con una opacidad del 10%
*/
.menu-bar > .container > .menu-button:hover{
-fx-background-color: rgba(0,0,0, 0.1);
}
/*
Cuando el usuario ha pinchado sobre el Menu y este muestra los Menu Items que tiene como hijos entonces
cambiamos el color a un negro con una opacidad del 30%
*/
.menu-bar > .container > .menu-button:showing{
-fx-background-color: rgba(0,0,0, 0.3);
}
El resultado lo podemos
observar en las siguientes imágenes:
Utilizando la pseudoclase
hover:
Utilizando la pseudoclase
showing:
Como se logra observar en
la primera imagen en donde utilice la pseudoclase hover el color del menú
cambio un verde mas oscuro debido al color negro con la opacidad de un 10%, en
cambio en la imagen en donde utilice la pseudoclase showing el verde es aún más
oscuro debido a que utilice un negro con una opacidad del 50%.
Hasta el momento solo le he
dado estilo a la barra de menú y al menú que esta contiene sin embargo, al pinchar
sobre ellos los nodos hijos que en esta caso son los menú ítems tienen el
diseño por defecto que trae el sistema operativo. Para entender como funciona
el despliegue de estos nodos hijos tenemos que saber que el evento que genera
el click sobre el menú hace que se muestre un context menú el cual tiene dentro
los menús ítems entonces a este vamos a darle el estilo de la barra de menú:
/**
Para acceder al context menu que muestra los menu items al pulsar sobre el menu-button accedemos a la clase css
.context-menu
*/
.context-menu{
/*Le damos el color de fondo que tiene nuestra menu bar*/
-fx-background-color: #00796B;
/*Le damos un padding de 5*/
-fx-padding: 5;
/*Le damos un ancho minimo de 100*/
-fx-min-width: 100;
}
.menu-item > .label{
/*Cambiamos el color del texto*/
-fx-text-fill: #FFFFFF;
/*Cambiamos el tamaño de la fuente*/
-fx-font-size: 14;
/*Cambiamos el tipo de fuente Nota: en mi caso utilizo la fuente roboto porque la tengo
instalada dentro de mi sistema operativo*/
-fx-font-family: "Roboto";
/*Colocamos el texto en negrita*/
-fx-font-weight: bold;
-fx-padding: 0;
}
.menu-item:hover{
-fx-background-color: rgba(0,0,0, 0.1);
}
.menu-item:showing{
-fx-background-color: rgba(0,0,0, 0.3);
}
.menu-item: focused{
-fx-background-color: rgba(0,0,0, 0.3);
}
Y ya con estos pasos
podemos ir realizando diseños mas llamativos y de acorde a nuestras necesidades
como desarrolladores.
A continuación, comparto el
código completo del FXML y del archivo css.
Código FXML y código css.
Codigo FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="@MenuBar.css" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>
Codigo css:
/*
Para acceder a la menubar utilizamod la clase css menu-bar.
Nota: en css de javafx hay muchas de las funciones del css
para el desarrollo web que no son aplicables.
*/
.menu-bar{
/*Le damos un background color de verde azulado*/
-fx-background-color: #00796B;
/*Le damos un padding de 5 */
-fx-padding: 5;
}
/*
Para acceder a los Nodos Menu que contiene la barra de menus utilizamos
la clase css .menu-button
*/
.menu-button{
/*
En esta seccion colocariamos el codigo css que deseamos aplicar a nuestro
nodo Menu
*/
}
/*
Para acceder al Label que muestra el texto del Menu entonces lo hacemos de la siguiente forma
.menu-bar > .container > . menu-button > .label
de esta forma podemos cambiar el color, tamaño tipo de fuente, padding entre otras funciones
cabe destacar que utilizando esta forma cambiaremos solamente los Label que se encuentran
dentro de la barra de menus ya que si solo utilizamos la clase .label el codigo css afectaría
a todos los Labels que contenga nuestro border pane
para esta prueba le cambiaré el color de texto, el tamaño de la fuente el tipo de fuente y el
tipo de letra
*/
.menu-bar > .container > .menu-button >.label{
/*Cambiamos el color del texto*/
-fx-text-fill: #FFFFFF;
/*Cambiamos el tamaño de la fuente*/
-fx-font-size: 18;
/*Cambiamos el tipo de fuente Nota: en mi caso utilizo la fuente roboto porque la tengo
instalada dentro de mi sistema operativo*/
-fx-font-family: "Roboto";
/*Colocamos el texto en negrita*/
-fx-font-weight: bold;
}
/*
Cuando el cursor del raton se encuentra sobre el menu cambiamos el color a negro pero con una opacidad del 10%
*/
.menu-bar > .container > .menu-button:hover{
-fx-background-color: rgba(0,0,0, 0.1);
}
/*
Cuando el usuario ha pinchado sobre el Menu y este muestra los Menu Items que tiene como hijos entonces
cambiamos el color a un negro con una opacidad del 30%
*/
.menu-bar > .container > .menu-button:showing{
-fx-background-color: rgba(0,0,0, 0.3);
}
.menu-item > .label{
/*Cambiamos el color del texto*/
-fx-text-fill: #FFFFFF;
/*Cambiamos el tamaño de la fuente*/
-fx-font-size: 14;
/*Cambiamos el tipo de fuente Nota: en mi caso utilizo la fuente roboto porque la tengo
instalada dentro de mi sistema operativo*/
-fx-font-family: "Roboto";
/*Colocamos el texto en negrita*/
-fx-font-weight: bold;
-fx-padding: 0;
}
.menu-item:hover{
-fx-background-color: rgba(0,0,0, 0.1);
}
.menu-item:showing{
-fx-background-color: rgba(0,0,0, 0.3);
}
.menu-item: focused{
-fx-background-color: rgba(0,0,0, 0.3);
}
/**
Para acceder al context menu que muestra los menu items al pulsar sobre el menu-button accedemos a la clase css
.context-menu
*/
.context-menu{
/*Le damos el color de fondo que tiene nuestra menu bar*/
-fx-background-color: #00796B;
/*Le damos un padding de 5*/
-fx-padding: 5;
/*Le damos un ancho minimo de 100*/
-fx-min-width: 100;
}
Comentarios