En esta segunda masterclass vamos a crear una aplicación de Java con interfaz de usuario en Swing empleando el diseñador del IntelliJ. Para ello creamos una pequeña calculadora como práctica. Primeramente vemos cómo establecer el diseño disponiendo los elementos mediante el gestor GridLayout y configurar las políticas de redimensionado para que se ajusten al tamaño de la ventana contenedora. Posteriormente, vemos cómo capturar sus eventos y manipular sus propiedades desde el código para implementar la lógica de la práctica.
Si no has visto el primer video/artículo de la serie, visítalo en este enlace: Introducción al IDE IntelliJ IDEA APPS JAVA (Parte 1)
En esta práctica vamos a ver el modo de implementar una calculadora sencilla empleando Swing y el diseñador del IDE IntelliJ IDEA.
El objetivo es crear una aplicación provista de un interfaz de usuario con una serie de botones y una etiqueta:
Para ello creamos una nueva aplicación Java llamada Calculadora sin especificar ninguna plantilla. A continuación, le añadimos un paquete y creamos el formulario principal haciendo clic sobre el mismo con el botón derecho y seleccionando la opción:
New -> Swing UI Designer -> GUI Form
Indicamos como nombre para la nueva ventana “Aplicación”:
Es importante dejar marcada la casilla “Create bound class” para que junto con el archivo de diseñó de la ventana genere una clase de Java donde implementaremos la funcionalidad de la ventana.
Se nos crea entonces la ventana provista de los siguientes archivos:
- java -> Incluye el código de una clase “Aplicacion” inicialmente vacía.
- form -> Incluye el diseño de la ventana.
Vista del GUI Designer del IntelliJ
Para agregar elementos a la ventana sólo necesitamos seleccionarlos en la pestaña “Palette” y arrastrarlos sobre el espacio de edición indicando la posición donde lo deseamos. Según vayamos situando los elementos, éstos aparecen en la pestaña “Component Tree” que muestra el orden de los componentes en el diseño ordenados jerárquicamente.
El componente base es un contenedor JPanel que contiene todos los elementos. Es importante darle un identificador, por ejemplo: “root”. Para ello, lo seleccionamos e introducimos el valor en la propiedad Field Name del espacio de propiedades.
Si estás interesado en aumentar tus en desarrollo de aplicaciones de escritorio, web, distribuidas y para dispositivos móviles , visita nuestros Cursos de Programación
Diseño de Interfaz
Añadimos el resto de elementos que componen el diseño:
- Un JPanel superior “Cabecera”
- Un JLabel “lblDisplay”
- Un JButton “btnReset” con propiedad Text = “R”.
- Un JPanel inferior “Botonera”
- 10 JButtons con los dígitos del 0 al 9
- 1 JButton con el “.”
- 4 JButtons con los signos de operación “+”, “-“, “x”, “/” e “=”.
Para disponer los elementos empleamos el gestor GridLayoutManager que divide el espacio de la ventana en una tabla de filas y columnas según se van añadiendo componentes.
Los componentes una vez situados quedan del siguiente modo:
En el panel superior “Cabecera”, el componente botón se configura con Horizontal Policy Fixed para que mantenga su ancho. La etiqueta se configura por el contrario como Want Grow para que su celda se expanda en función del ancho de la ventana. Para que la etiqueta ocupe todo el ancho de la celda se asigna el valor Fill a su propiedad Horizontal Align, y para que su texto se justifique a la derecha se asigna Right a su propiedad HorizontalAlignament. Por último que los componentes incluidos en este JPanel mantengan su altura independiente del de la ventana debe ajustarse su propiedad Vertical Size Policy en Fixed.
En el panel inferior “Botonera” su propiedad Vertical Size Policy y Horizontal Size Policy se ajustan como Can Grow para adaptarse el ancho y alto de la ventana. Los botones de las tres primeras columnas se disponen indicando Horizontal Policy Can Grow de modo que repartan en sus anchos proporcionalmente el ancho de la ventana. Los botones de la cuarta columna incluyen además un Preferred Size de 100 píxels para mostrar un tamaño proporcionalmente mayor. Las propiedades Vertical Align y Horizontal Align de todos ellos se ajustan en Fill para que ocupen el ancho y alto completo de las celdas que los contienen.
Al indicar un identificador para cada uno de los botones se generan las variables correspondientes para referenciarlos en el código de la clase vinculada:
Captura de eventos
Para la captura de eventos hacemos clic con el botón derecho sobre un componente y seleccionamos la opción “Create Listener”.
Seguidamente seleccionamos el interfaz escuchador y la función que deseamos capturar. Si deseamos capturar el evento de “clic” sobre los botones debemos capturar la función actionPerformed() del interfaz escuchador ActionListener:
Si capturamos el evento para un único botón, por ejemplo; el botón “R” (btnReset) se añade un constructor a la clase vinculada donde se invoca al método addActionListener() del botón asignando como argumento un objeto anónimo que implementa el método actionPerformed() de la interfaz escuchadora ActionListener:
El código que incluyamos dentro de la función actionPerformed() será el que se ejecute cuando el botón sea pulsado por el usuario.
Si deseamos capturar el mismo evento para diferentes botones dado que todos van a realizar la misma acción al ser pulsados podemos seleccionarlos y realizar la misma operación. Hacemos clic con el botón derecho sobre un componente y seleccionamos la opción “Create Listener”.
Se añade entonces al constructor la declaración de un objeto anónimo listenerDigitos que implementa la interfaz ActionListener y el método actionPerformed(), y se asigna como argumento al método addActionListener() de todos los botones:
Al igual que antes, el código suministrado al método actionPerformed() del objeto anónimo será el que se ejecute al hacer clic sobre cualquiera de los botones.
Por último repetimos esta misma operación con los botones correspondientes a las operaciones “+”, “-“, “x”, “/” e “=”. Se genera entonces el objeto anónimo listenerOperaciones.
Implementación de acciones.
Ahora es el momento de añadir código a las funciones manejadoras de los eventos capturados previamente para implementar las operaciones necesarias.
En el caso de que se pulse el botón “R”, deseamos que el componente etiqueta JLabel (lblDisplay) se quede vacío sin mostrar ningún contenido. Para ello debemos alterar el valor de su propiedad de diseño text mediante su método setText():
En el caso de los botones de dígitos, la acción a realizar es añadir el dígito pulsado al contenido mostrado por el componente etiqueta JLabel (lblDisplay). Para lo cual, podemos obtener primero la cadena con su contenido mediante su método getText(), concatenar el dígito del botón pulsado, y volvérsela a asignar al componente mediante su método setText().
Para obtener el dígito del botón pulsado (puesto que pueden ser varios en este caso), debemos obtener la referencia al objeto origen del evento mediante el método getSource() del parámetro ‘e’ del método actionPerformed(). Obtenida la referencia al botón pulsado, empleamos su método getText (como en el JLabel) para obtener su dígito.
En el caso de los botones de operadores el proceso es parecido.
Necesitamos igualmente que se añada el signo del operador del botón pulsado al contenido del componente etiqueta, salvo que se trate del botón “=”:
Sin embargo, aquí necesitamos que se calcule el resultado de la expresión presente en el componente etiqueta ANTES de añadir el signo pulsado. De este modo, si tenemos la expresión:
10+20
Y pulsamos “+”, queremos que el resultado mostrado sea:
30+
Y si pulsamos “=”, obtendríamos simplemente el resultado:
30
Para ello debemos construir una función que dada una cadena con una expresión aritmética como “10+20” nos retorne una cadena con el resultado correspondiente.
La función de cálculo
Para el propósito de resolver las operaciones que se va introduciendo el usuario sucesivamente empleamos el siguiente método que añadimos a la clase vinculada.
Para ello creamos un método que realiza las siguientes operaciones:
Esta función emplea una expresión regular y el método split() para segmentar la cadena empleando cualquier operador “+”,”-“,”x”,”/” como carácter separador. El resultado es una matriz de cadenas de caracteres con los fragmentos resultantes.
String[] ops = operacion.split(«[\\+\\-X\\/]»);
Seguidamente, Si el resultado es una matriz de una única cadena, significa que la expresión únicamente tiene un valor, y el resultado es por tanto ese mismo valor.
if ( ops.length == 1 ) {
resultado = ops[0];
Si, por el contrario, el resultado es una matriz de más posiciones significa que hay una expresión a resolver. Para ello, se convierten a tipo numérico el contenido de ambas posiciones de la matriz, y se detecta cuál de los operadores está contenido en la cadena mediante el método contains(). Se realiza el cálculo correspondiente y se convierte el resultado en cadena para retornarlo.
} else {
float v1 = Float.parseFloat(ops[0]); // conversión a float de valor cadena 1
float v2 = Float.parseFloat(ops[1]); // conversión a float de valor cadena 2
float r;
if ( operacion.contains(«+»)) r = v1 + v2;
else if ( operacion.contains(«-«)) r = v1 – v2;
else if ( operacion.contains(«X»)) r = v1 * v2;
else r = v1 / v2;
resultado = String.valueOf(r);
El código del método queda finalmente del siguiente modo:
Por último, sólo nos resta añadir la llamada al método desde el método actionPerformed() del objeto escuchador listenerOperaciones:
Y con esta última llamada quedaría completamente funcional el código de nuestra calculadora.
Lanzando la aplicación.
Para poder ejecutar nuestra calculadora necesitamos hacer que la clase vinculada sea ejecutable. Para ello, es necesario que tenga un método estático main().
Este puede generarse automáticamente haciendo clic con el botón derecho sobre el editor de código de la clave asociada y seleccionar la opción:
Generate… -> Form main()
Esto genera una función main() que instancia un objeto JFrame y le añade el componente JPanel raíz (root) que incluye todos los componente y contenedores que hemos añadido en el diseño:
Una vez añadida la función main(), la clase pasa a ser ejecutable y podemos lanzarla haciendo clic con el botón derecho sobre ella en la pestaña Project y seleccionando la opción: “Run aplicación.main()”:
Una vez lanzada una vez, es posible volver a lanzar la aplicación pulsando el botón situado en la barra de botones del extremo superior derecho:
Tutorial paso a paso: Comenzando a programar en Java con IntelliJ IDEA ( parte 2 ).
Si estás interesado en aumentar tus en desarrollo de aplicaciones de escritorio, web, distribuidas y para dispositivos móviles , visita nuestros Cursos de Programación