Manejo de eventos con clases anidadas. Por lo general un usuario interactúa con una GUI para indicar las tareas que ésta debe realizar. Por ejemplo, al escribir un mensaje de correo electrónico, pulsamos el botón “enviar” para indicar a la aplicación que envíe el mensaje a las direcciones especificadas. Las GUIs son controladas por eventos. Cuando el usuario interactúa con un componente de la GUI, la interacción (conocida como un evento) controla el programa para que realice una tarea. Algunos eventos (interacciones con el usuario) comunes que podrían hacer que una aplicación realizara una tarea incluyen el hacer clic en un botón, escribir en un campo de texto, seleccionar un elemento de un menú, cerrar una ventana y mover el ratón. El código que realiza una tarea en respuesta a un evento se llama manejador de eventos y al proceso en general de responder a los eventos se le conoce como manejo de eventos. Pasos requeridos para establecer el manejo de eventos para un componente de GUI. Antes de que una aplicación pueda responder a un evento para un componente de GUI especifico, debemos realizar varios pasos de codificación: 1. Crear una clase que represente al manejador de eventos. 2. Implementar una interfaz apropiada, conocida como interfaz de escucha de eventos, en la clase del paso 1. 3. Indicar que se debe notificar a un objeto de la clase de los pasos 1 y 2 cuando ocurra el evento. A esto se le conoce como registrar el manejador de eventos. Uso de una clase anidada para implementar un manejador de eventos. Java nos permite declarar clases dentro de otras clases; a éstas se les conoce como clases anidadas. Las clases anidadas pueden ser static o no static. Las clases no static se llaman clases internas, y se utilizan con frecuencia para el manejo de eventos. Observación importante. Una clase interna puede acceder directamente a las variables y métodos de su clase de nivel superior, aun cuando sean private. Antes de poder crear un objeto de una clase interna, debe haber primero un objeto de la clase de nivel superior que contenga a la clase interna. Esto se requiere debido a que un objeto de la clase interna tiene implícitamente una referencia a un objeto de su clase de nivel superior. También hay una relación especial entre estos objetos: el objeto de la clase interna puede acceder directamente a todas las variables de instancia y métodos de la clase externa. Ing. Leonardo R. L. Tópicos Selectos de Programación Pág. 1 Ejemplo 1. Crear una interfaz gráfica de usuario GUI en Java, que procese un dato de tipo numérico, y luego mediante un interfaz de eventos, calcule y regrese la potencia al cuadrado del mismo. /* Programa: Calculadora de potencias de un número al cuadrado, utilizando una GUI y manejo de eventos * Autor: Ing. Leonardo Ramírez L. * Curso: Tópicos Selectos de Programación, unidad IV */ //importamos las bibliotecas de la API de Java import javax.swing.*; //swing, para interfaz gráfica import java.awt.*; //awt, para elementos interactivos import java.awt.event.*; //awt.event, para el manejo de eventos //La clase principal o superior, "Eventos" que hereda las características de la clase JFrame public class Eventos extends JFrame { //declaración de los atributos de nuestra Interfaz Gráfica de Usuario private JPanel panelPrincipal; //declaración del panel que contiene a los componentes private JLabel etiqueta; //declaración de la etiqueta "Introduzca un número" private JTextField campo; //declaración de un campo de texto combinado private JButton boton; // declaración de el botón para lanzar el evento //constructor por defecto para lanzar la GUI "Eventos" sin parámetros public Eventos () { //inicialización de los componentes de la interfaz super("Calculadora de potencia cuadrada"); //establecer el título de la ventana setSize(200,200); //establecer el tamaño de la ventana, ancho = 200 y alto = 200 (pixeles) setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //establecer salida por defecto del sistema si la ventana se cierra desde el botón cerrar ventana //instancias de los componentes de la interfaz panelPrincipal = new JPanel( new FlowLayout() ); //instancia panelPrincipal con arreglo de componentes tipo FlowLayout(), un componente tras otro etiqueta = new JLabel("Introduzca un numero"); //instancia de la etiqueta de información de datos con el texto "Introduzca..." campo = new JTextField("0.0",10); //instancia del campo combinado, asignando el valor de "0.0" como valor por default y estableciendo un ancho de 10 columnas para el campo boton = new JButton("Potenciar");//instancia del botón "Potenciar" //agregar los componentes a la interfaz //primero, agregamos el panelPrincipal, a la ventana principal add(panelPrincipal); //luego, agregamos todos los demás componentes al panelPrincipal panelPrincipal.add(etiqueta); panelPrincipal.add(campo); panelPrincipal.add(boton); //una vez, que están todos los componentes hacemos la interfaz visible setVisible(true); //aquí, instanciamos el "escuchador de eventos" desde la clase interna ManejoEventos ManejoEventos escuchador = new ManejoEventos (); //el objeto "escuchador", espera que ocurra un evento //luego, registramos el "objeto evento" en el botón que lanza el interfaz de escucha de eventos boton.addActionListener(escuchador); }//termina el constructor de la interfaz gráfica Ing. Leonardo R. L. Tópicos Selectos de Programación Pág. 2 /* Declaramos la clase interna ManejoEventos, que implementa los métodos para "escuchar eventos" a través * de la clase ActionListener. * En ésta clase declaramos un método actionPerformed (acción realizada) que será la interfaz del escuchador, * y que contiene lo que va a "ocurrir" una vez presionado el botón "Potenciar" */ private class ManejoEventos implements ActionListener { //declaración del método actionPerformed, que va a contener los pasos que hará nuestro programa //una vez, pulsado el botón "potenciar" public void actionPerformed (ActionEvent evento) //el parámetro de entrada, es del tipo ActionEvent, y registra los datos cómo de dónde se originó el evento, etc { String valorEnTexto = campo.getText(); //se obtiene el dato del campo combinado y se asigna en la variable de texto valorEnTexto, utilizando el método getText() en el campo combinado double valorAPotenciar = Double.parseDouble(valorEnTexto); //se convierte el dato de texto a número utilizando el método parseDouble() de la clase Double y se asigna en la variable double valorAPotenciar double valorPotenciado = Math.pow(valorAPotenciar, 2); //elevamos al cuadrado el número anterior, y luego lo asignamos a la variable double valorPotenciado String valorPotenciadoEnTexto = String.valueOf(valorPotenciado); //convertimos ValorPotenciado en texto utilizando el método valueOf() de la clase String, y lo asignamos en valorPotenciadoEnTexto campo.setText(valorPotenciadoEnTexto); //establecemos el contenido del campo combinado, enviando la variable ValorPotenciadoEnTexto, utilizando el método setText() del objeto campo } //termina el método actionPeformed }//termina la clase privada ManejoEventos, de la interfaz de escucha de eventos //declaración del método principal main, de dónde inicia nuestro programa public static void main (String [] args) { //instancia de la GUI en un objeto de nombre ventana Eventos ventana = new Eventos (); //instancia de la clase Eventos, que contiene la GUI y el interface de escucha de eventos que son cargados en el objeto ventana } //fin del método estático principal main } //fin de la clase Eventos Visualización de la interfaz gráfica de usuario 1. GUI creada a partir de la instancia de la clase Eventos Ing. Leonardo R. L. 2. Introducimos 2.5 en el campo combinado y luego pulsamos el botón “Potenciar” Tópicos Selectos de Programación 3. El manejador de enventos “lanza” el procedimiento y eleva el valor al cuadrado, y lo muestra en el campo combinado Pág. 3 Ejemplo 1.B. Crear una interfaz gráfica de usuario GUI en Java, que procese un dato de tipo numérico, y luego mediante un interfaz de eventos, calcule y regrese la potencia al cuadrado del mismo. Además, la interfaz gráfica debe implementar 3 botones, uno para procesar el valor al cuadrado, otra para borrar (resetear) el valor y uno más para salir del programa (enviando un saludo de despedida al usuario). /* * Programa: Calculadora de potencias, con boton borrar y boton salir * Autor: Ing. Leonardo R. L. * Lenguaje: Java SE */ import javax.swing.*; import java.awt.*; import java.awt.event.*; // 1er paso, Implementación de la Interfaz Gráfica de Usuario public class Eventos extends JFrame { private private private private private private JPanel panelPrincipal; //panel para los componentes JLabel etiqueta; //"ingresa un numero" JTextField campo; //cuadro combinado de texto JButton botonProcesar; //boton para lanzar el evento procesar JButton botonBorrar; //botón para lanzar el evento borrar JButton botonSalir; //botón para lanzar el evento salir //2do paso, inicializar componentes de la GUI, en el constructor por defecto public Eventos () { setTitle("Calculadora de potencias"); //titulo de la ventana setLocation(540, 300); //centrar la GUI en la pantalla en modo de 1280 x 800 setSize(200, 200); //200 de ancho, por 200 de alto setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //salir del programa al pulsar el boton X //instancias de los componentes de la GUI panelPrincipal = new JPanel(); //inicializacion del panel, con FlowLayout() etiqueta = new JLabel ("Ingresa un numero:"); campo = new JTextField("0.0",10); botonProcesar = new JButton("Procesar"); botonBorrar = new JButton ("borrar"); botonSalir = new JButton ("Salir"); //agregar componentes al panel panelPrincipal.add(etiqueta); panelPrincipal.add(campo); panelPrincipal.add(botonProcesar); panelPrincipal.add(botonBorrar); panelPrincipal.add(botonSalir); //agregar panel a la ventana add(panelPrincipal); setVisible(true); //instanciar el "escuchador" de la clase interna ManejoDeEventos ManejoDeEventos escuchador = new ManejoDeEventos(); Ing. Leonardo R. L. Tópicos Selectos de Programación Pág. 4 //registrar el "escuchador" en todos los componentes campo.addActionListener(escuchador); botonProcesar.addActionListener(escuchador); botonBorrar.addActionListener(escuchador); botonSalir.addActionListener(escuchador); } //termina constructor //3er paso, crear la clase interna ManejoDeEventos e implementar el interfaz de eventos private class ManejoDeEventos implements ActionListener { //declarar el método actionPerformed, que atenderá el programa cuando un evento ocurra public void actionPerformed (ActionEvent evento) { //utilizamos, el método getSource referido al objeto "evento" que devuelve el origen del evento if (evento.getSource() == botonProcesar) { String valorTexto = campo.getText(); double valorReal = Double.parseDouble(valorTexto); double potencia = Math.pow(valorReal, 2); campo.setText(String.valueOf(potencia)); } if (evento.getSource() == botonBorrar) { campo.setText("0.0"); } if (evento.getSource() == botonSalir) { JOptionPane aviso = new JOptionPane(); aviso.showMessageDialog(null, "Gracias por utilizar nuestro programa"); System.exit(0); } } //fin del método actionPerformed } //fin de la clase interna ManejoDeEventos //método estático principal main public static void main (String [] args) { Eventos ventana = new Eventos(); } //fin del método principal main } //fin de la clase Eventos Visualización de la interfaz gráfica de usuario. 1.GUI creada a partir de la clase Eventos Ing. Leonardo R. L. 2. Introducimos 10.0 en el campo combinado y pulsamos “Procesar” Tópicos Selectos de Programación 3. Se muestra el resultado, y podemos volver al paso 1, pulsando el botón “borrar” Pág. 5 Ejemplo 2. Crear una calculadora que efectúe las 4 operaciones básicas (suma, resta, multiplicación y división), con cuatro números reales. La interfaz gráfica de usuario, debe incorporar un botón de evento para cada proceso, y un botón para borrar todos los datos. import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Operadores extends JFrame { private private private private private private private private private JPanel panel; JLabel et_1; JLabel et_2; JLabel et_3; JLabel et_4; JTextField num_1; JTextField num_2; JTextField num_3; JTextField num_4; private private private private private JButton JButton JButton JButton JButton sumaB; restaB; multB; divB; borrarB; public Operadores () { //parámetros para la interfaz gráfica de usuario setTitle("Operadores aritmeticos"); setSize(230,280); setLocation(400,400); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); panel = new JPanel(new FlowLayout()); et_1 = new JLabel ("Ingresa el 1er numero:"); et_2 = new JLabel ("Ingresa el 2do numero:"); et_3 = new JLabel ("Ingresa el 3er numero:"); et_4 = new JLabel ("Ingresa el 4to numero:"); num_1 = new JTextField ("0.0",2); num_2 = new JTextField ("0.0",2); num_3 = new JTextField ("0.0",2); num_4 = new JTextField ("0.0",2); sumaB = new JButton ("Sumar"); restaB = new JButton ("Restar"); multB = new JButton ("Multiplicar"); divB = new JButton ("Dividir"); borrarB = new JButton ("Borrar"); add(panel); panel.add(et_1); panel.add(num_1); Ing. Leonardo R. L. Tópicos Selectos de Programación Pág. 6 panel.add(et_2); panel.add(num_2); panel.add(et_3); panel.add(num_3); panel.add(et_4); panel.add(num_4); panel.add(sumaB); panel.add(restaB); panel.add(multB); panel.add(divB); panel.add(borrarB); //instancia el escuchador desde la clase ManejoDeEventos ManejoDeEventos escuchador = new ManejoDeEventos(); //registrar el escuchador en los componentes sumaB.addActionListener(escuchador); restaB.addActionListener(escuchador); multB.addActionListener(escuchador); divB.addActionListener(escuchador); borrarB.addActionListener(escuchador); setVisible(true); } //fin del constructor public class ManejoDeEventos implements ActionListener { public void actionPerformed (ActionEvent evento) { //capturar en texto todos los valores de los campos combinados String String String String n1 n2 n3 n4 = = = = num_1.getText(); num_2.getText(); num_3.getText(); num_4.getText(); //convertir los valores de texto a números reales double double double double numero1 numero2 numero3 numero4 = = = = Double.parseDouble(n1); Double.parseDouble(n2); Double.parseDouble(n3); Double.parseDouble(n4); //si el evento se originó en el botón suma if (evento.getSource() == sumaB) { double suma = numero1 + numero2 + numero3 + numero4; JOptionPane aviso = new JOptionPane(); aviso.showMessageDialog(null, String.valueOf(suma), "La suma es",0); } //si el evento se originó en el botón resta if (evento.getSource() == restaB) { double resta = numero1 - numero2 - numero3 - numero4; JOptionPane aviso = new JOptionPane(); aviso.showMessageDialog(null, String.valueOf(resta), "La resta es",1); } //si el evento se originó en el botón multiplicación if (evento.getSource() == multB) { double multiplicacion = numero1 * numero2 * numero3 * numero4; JOptionPane aviso = new JOptionPane(); Ing. Leonardo R. L. Tópicos Selectos de Programación Pág. 7 aviso.showMessageDialog(null, String.valueOf(multiplicacion), "La multiplicación es",2); } //si el evento se originó en el botón división if (evento.getSource() == divB) { double division = numero1 / numero2 / numero3 / numero4; JOptionPane aviso = new JOptionPane(); aviso.showMessageDialog(null, String.valueOf(division), "La división es",3); } //si el evento se originó en el botón borrar if (evento.getSource() == borrarB) { num_1.setText("0.0"); num_2.setText("0.0"); num_3.setText("0.0"); num_4.setText("0.0"); } } //fin del método actionPerformed } //fin de la clase interna ManejoDeEventos //método estático principal main public static void main (String [] args) { Operadores ventana = new Operadores(); } //fin del método main } //fin de la clase principal Operadores Apariencia visual de la interfaz gráfica de usuario Evento correspondiente a la pulsación de cada botón de la GUI Ing. Leonardo R. L. Tópicos Selectos de Programación Pág. 8