Objetivo interfas a codigo

208 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
208
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
10
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Objetivo interfas a codigo

  1. 1. Objetivo: Introducir al estudiante en la programación de interfaces graficas de usuario utilizando Java A quien está dirigido: Estudiantes con conocimientos básicos de programación orientada a objetos con Java, en particular deben de conocer los conceptos de:  Clases  Objetos  Herencia  Clases abstractas e interfaces Competencia esperada: Al concluir el presente tutorial el estudiante debe de comprender que partes de la API de Java puede utilizar para construir interfaces graficas de usuario (GUIs), y la forma en que Java implementa el patrón observer. Estilo: Guía paso a paso, el lector encontrará varias versiones del código, hacemos esto para enfatizar lo que hace cada parte del código. Interfaces graficas en Java Para empezar la discución de como realizar interfaces graficas en Java, debemos primero realizar algunas aclaraciones:  El concepto de "Interfaz de usuario" se refiere a los mecanismos para construir ventanas, botones, menus, etc que permiten crear una interfaz amigable para nuestros programas y no al concepto de "interface" que existe en Java y que se refiere a una especie de clase abstracta pura.  Los mecanismos para crear "interfaces de usuario" en Java están pensados para favorecer la creación de la lógica de negocio separada de la creación de la interfaz de usuario. Sin embargo, no hay garantía de que esto suceda. Es responsabilidad del programador cristalizar este objetivo. Para poder lograrlo le sugerimos al lector estudiar el patron de diseño conocido como MVC. Ligas a MVC: Spring Tutorial Patron  Para el manejo de eventos Java utiliza un modelo en el cual existe un "ente" generador de eventos y otros "entes" interesados en dar respuesta a los eventos. Cuando un evento se produce, el generador del evento avisa a todos los "entes" que hayan manifestado su interes en el evento. Y cada uno de los interesados responderá al evento utilizando su propia lógica. Para mayor claridad construiremos un ejemplo completo poco a poco; sin embargo debemos advertir que se asume que el lector está familiarizado con conceptos como: clase, objeto, mensaje, constructora, referencias, imports,
  2. 2. herencia e interfaces. Construiremos una calculadora de senos, cosenos y tangentes de ángulos. Construcción de una ventana 1 import javax.swing.*; 2 3 public class Trigo extends JFrame{ 4 5 } En la primera línea simplemente importamos el paquete donde está definida la clase JFrame. Un JFrame es la clase que representa al tipo "Ventana". En otras palabras un "JFrame" es una ventana del sistema operativo. Como nuestra clase hereda (extienda) a la clase JFrame, Trigo será por lo tanto también un JFrame es decir una ventana. Para comprobar esto añadiremos a nuestra clase un método "main", quedando ahora de la siguiente forma: 1 import javax.swing.*; 2 3 public class Trigo extends JFrame{ 4 public static void main(String[] arg){ 5 Trigo miAplicacion = new Trigo(); 6 miAplicacion.setBounds(10,10,200,200); 7 miAplicacion.pack(); 8 miAplicacion.setVisible(true); 9 } 10 } Todos los mensajes enviados al objeto "miAplicacion" son métodos heredados de "JFrame". El primer método "setBounds" establece la posición inicial de la ventana en la pantalla y sus dimensiones. El segundo, "pack", en este momento no era realmente necesario ya que la ventana está vacia; pero quisimos incluirlo para no tener que modificar el main más tarde. Este método optimiza la disposición de los elementos dentro de la ventana. Y el último mensaje es simplemente para ordenarle a la venta que se haga visible. Después de compilar y ejecutar el código verá en pantalla algo como lo mostrado en la figura 1.
  3. 3. figura 1 Agregando un botón La ventana (JFrame) sólo puede contener dos cosas: un menu, y un panel. Cada uno de estos elementos con su espacio ya determinado. Por el momento no utilzaremos el menú. Los botones y demás elementos a agregar no se colocan directamente en la ventana, sino en un objeto interno, el "Panel". Este objeto interno a su vez utiliza otro objeto interno conocido como LayoutManager, que se encarga de controlar la disposción de los elementos dentro del panel. Existen muchos LayoutManagers, cada uno con su propia lógica para la dispocisión de los elementos, aqui ejemplificaremos el uso de un par de ellos. Modificamos nuestra clase para agragar un botón quedando entonces como: 1 import javax.swing.*; 2 import java.awt.*; 3 4 public class Trigo extends JFrame{ 5 private JButton b1; 6 7 public Trigo(){ 8 b1 = new JButton("seno"); 9 this.getContentPane().add(b1,BorderLayout.NORTH); 10 } 11 public static void main(String[] arg){ 12 Trigo miAplicacion = new Trigo(); 13 miAplicacion.setBounds(10,10,200,200); 14 miAplicacion.pack(); 15 miAplicacion.setVisible(true); 16 } 17 } Después de compilar y ejecutar el código tendremos algo como:
  4. 4. Figura 2 Ahora el tamaño de la ventana cambio y se adapto al único elemento que contiene (el botón). El significado del código agregado es el siguiente: En la línea 2 importamos el paquete donde se encuentra declarado la clase "BorderLayout". Incluimos un "JButton" (un botón) como atributo de nuestra clase "Trigo" y agregamos además una constructora, que es donde creamos el objeto "b1" para después añadirlo al panel de la ventana con la instrucción de la línea 9. Esta última instrucción merece la pena una explicación ya que la utilizaremos bastante a través del ejemplo. La parte que a continuación se muestra en azul se encarga de obtener una referencia al panel de la ventana. this.getContentPane().add(b1,BorderLayout.NORTH); Mientras que la parte que se encuentra en rojo es la que le ordena al Panel que agregue el botón, además de que le ordena que para añadirlo utilice un "LayoutManager" de tipo "BorderLayout". Este tipo de "LayoutManager" divide al panel en 5 regiones (Norte, Sur, Este, Oeste y Centro); donde cada región puede contener sólo un elemento. En este caso añadimos el botón a la zona "Norte" y para ordenarlo utilizamos la constante de clase "NORTH" definida en la clase "BorderLayout". De forma analoga incluiremos un campo de texto "JTextField" en la zona "Sur" de nuestro panel. 1 import javax.swing.*; 2 import java.awt.*; 3 4 public class Trigo extends JFrame{ 5 private JButton b1; 6 private JTextField campo1; 7 8 public Trigo(){ 9 b1 = new JButton("seno"); 10 campo1 = new JTextField(); 11 this.getContentPane().add(b1,BorderLayout.NORTH); 12 this.getContentPane().add(campo1,BorderLayout.SOUTH); 13 } 14 public static void main(String[] arg){ 15 Trigo miAplicacion = new Trigo(); 16 miAplicacion.setBounds(10,10,200,200); 17 miAplicacion.pack(); 18 miAplicacion.setVisible(true);
  5. 5. 19 } 20 } Figura 3 Para que observe bien la definición de zonas hechas en el panel por el "BorderLayout" aumente la ventana y verá que el centro queda un espacio vacío (la parte gris), ya que el botón se encuentra al Norte y el campo de Texto al Sur. Figura 4 Añadiendo acciones al boton Hasta ahora sólo hemos mostrado como agregar elementos a la ventana, ya tenemos dos elementos un botón y un campo de texto. Sin embargo, el botón al ser oprimido no produce ninguna acción. El botón es el ente que genera eventos (es oprimido) pero no existe hasta el momento ningún objeto interesado en sus eventos. Es decir que no existe ningún oyente de los eventos. Para registrar un oyente el botón cuenta con el métodoaddActionListener. La firma del este método es: void addActionListener(ActionListener evento) Esto significa que el elemento a registrarse como oyente de los eventos del botón debe ser un "ActionListener". Para nuestro ejemplo, lo que deseamos es que la ventana que contiene al botón "miAplicacion" sea la que se registre con el botón como oyente de eventos. El problema con esto es que "miAplicacion" es de tipo "Trigo" o bien de tipo "JFrame" pero no es un "ActionListener". Para que las instancias de tipo "Trigo" también sean de tipo "ActionListener" tenemos que
  6. 6. hacer que la clase "Trigo" implemente la interfaz "ActionListener"; porque de forma analoga a lo que sucede con la herencia (extends) cuando una clase implementa una interfaz se establece una relación "es un" entre ellas. Para anunciar que "Trigo" implementara la interfaz "ActionListener" modificamos la definición de la clase de la siguiente forma: public class Trigo extends JFrame implements ActionListener El hecho de afirmar que la clase "Trigo" implementa la interfaz "ActionListener" implica que ahora esta clase contiene todos los métodos definidos en la interfaz. Cabe recordar que todos los métodos de una interfaz son abstractos por lo tanto o sobre-escribimos los métodos agregandoles un cuerpo o bien tendremos que declarar a nuestra clase "Trigo" como abstracta. Como en nuestro ejemplo no deseamos que nuestra clase "Trigo" sea abstracta implementaremos todos los métodos de la interfaz "ActionListener". Afortunadamente, esta interfaz sólo define un método: public void actionPerformed(ActionEvent e) Este será el método que autómaticamente será ejecutado cuando el botón le avise de su evento a la ventana. Para fines de este ejemplo deseamos que la acción a realizar cuando se oprima el botón sea que en el campo de texto aparezca un letrero en que se diga cuantas veces ha sido oprimido el botón. Por lo tanto incluiremos una nueva variable (para contar el número de clicks sobre el botón, linea 8), el método "actionPerformed" (de la linea 18 a la 21) y cambiaremos la deficinición de la clase (linea 5). Ademas de registrar a la ventana como oyente de los eventos del botón (linea 12). Quedando por lo tanto nuestra clase como: 1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.*; 4 5 public class Trigo extends JFrame implements ActionListener{ 6 private JButton b1; 7 private JTextField campo1; 8 private int numClicks = 0; 9 10 public Trigo(){ 11 b1 = new JButton("seno"); 12 b1.addActionListener(this); 13 campo1 = new JTextField(); 14 this.getContentPane().add(b1,BorderLayout.NORTH); 15 this.getContentPane().add(campo1,BorderLayout.SOUTH); 16 } 17 18 public void actionPerformed(ActionEvent e){ 19 numClicks++;
  7. 7. 20 campo1.setText(numClicks+""); 21 } 22 23 public static void main(String[] arg){ 24 Trigo miAplicacion = new Trigo(); 25 miAplicacion.setBounds(10,10,200,200); 26 miAplicacion.pack(); 27 miAplicacion.setVisible(true); 28 } 29 } Prueba ahora dando clicks al botón. Armando la calculadora El ejemplo anterior sirve para mostrar los conceptos básicos, pero la promesa era hacer una calculadora de funciones trigonometricas. El primer paso que realizaremos será modificar un poco la interfaz, dejaremos el TextField como medio de entrada para el ángulo del que deseamos saber el seno, y añadiremos otro TextField para reportar el resultado del cálculo realizado. Tambien incluiremos unas etiquetas para marcar la entrada y salida de nuestra calculadora. Eliminaremos la variable que cuenta los clicks y para mostrar que los Paneles pueden contener otros paneles utilizaremos un par de paneles para ir organizando nuestra interfaz. 1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.*; 4 5 public class Trigo extends JFrame implements ActionListener{ 6 private JButton b1; 7 private JTextField campo1; 8 private JTextField campo2; 9 private JLabel etq1; 10 private JLabel etq2; 11 private Panel panelEntrada, panelSalida; 12 private JPanel panelDeLaVentana; 13 14 public Trigo(){ 15 //Creamos el boton 16 b1 = new JButton("seno"); 17 18 //Registramos a la ventana como oyente 19 b1.addActionListener(this); 20 21 //Creamos las etiquetas 22 etq1 = new JLabel("Angulo: "); 23 etq2 = new JLabel("Resultado: "); 24 25 //Creamos los campos de Texto 26 campo1 = new JTextField();
  8. 8. 27 campo2 = new JTextField(); 28 29 //Cambiamos la propiedades de los TextFields 30 campo2.setEditable(false); 31 campo2.setColumns(10); 32 campo2.setBackground(Color.lightGray); 33 campo1.setColumns(10); 34 35 //Creamos los paneles auxiliares 36 panelEntrada = new Panel(); 37 panelSalida = new Panel(); 38 39 //Obtenemos la referencia al panel principal 40 panelDeLaVentana = (JPanel)this.getContentPane(); 41 42 //Agregamos los componentes del panel de entrada 43 panelEntrada.add(campo1,BoxLayout.X_AXIS); 44 panelEntrada.add(etq1,BoxLayout.X_AXIS); 45 46 //Agregamos los componentes del panel de salida 47 panelSalida.add(campo2,BoxLayout.X_AXIS); 48 panelSalida.add(etq2,BoxLayout.X_AXIS); 49 50 //Agregamos todo al panel Principal 51 panelDeLaVentana.add(panelEntrada,BorderLayout.NORTH); 52 panelDeLaVentana.add(b1,BorderLayout.CENTER); 53 panelDeLaVentana.add(panelSalida,BorderLayout.SOUTH); 54 } 55 56 public void actionPerformed(ActionEvent e){ 57 } 58 59 public static void main(String[] arg){ 60 Trigo miAplicacion = new Trigo(); 61 miAplicacion.setBounds(10,10,200,200); 62 miAplicacion.pack(); 63 miAplicacion.setVisible(true); 64 } 65 } Ahora despues de compilar y ejecutar tendremos: Figura 5 En la discusión anterior habiamos mencionado que un "BorderLayout" sólo te permite poner una sola cosa en cada una de las regiones. Esta regla se sigue cumpliendo, el "BorderLayout" del panel principal contiene una sola cosa en la
  9. 9. region Norte (linea 51); contiene el Panel llamado "panelEntrada", es este panel el que a su vez contiene dos cosas una etiqueta y un campo de texto (lineas 43 y 44) utilizando su propia lógica para la disposición de los elementos, en este caso utilizando un BoxLayout. Para la parte de la salida es algo similar, pero observe además que la región del centro del panel principal "panelDeLaVentana" esta ocupada por el botón. De nueva cuenta una vez con la interfaz organizada procederemos a darle funcionalidad al botón. Parte del trabajo ya está hecho:  La ventana ya es un "ActionListener" (implementa la interfaz "ActionListener")  El botón ya registra a la venta como oyente de eventos (linea 19)  La clase "Trigo" ya tiene un método "actionPerformed", aunque vacío Por lo tanto sólo nos falta esribir la lógica de ejecución para responder al evento del botón. Lo que deseamos ahora ejecutar como respuesta al evento puede resumirse en 3 sencillos pasos: 1. Leer el ángulo proporcionado en el "TextField" de entrada (campo1). 2. Calcular el seno del ángulo proporcionado 3. Escribir el resultado en el campo de texto correspondiente (campo2) Al observar la API podemos darnos cuenta que entre el hecho de leer la entrada y calcular el seno hay un paso adicional, porque el "TextField" reporta su contenido como un "String" mientras que la función para calcular el seno, definida en el paquete Math de Java, utiliza un "double" como entrada. Por lo tanto, tendremos que convertir la cadena de caracteres en un double para después calcular el seno. Para realizar esta conversión utilizaremos el método "parseDouble" definido en la "Wrapper class" Double. Double.parseDouble(String val) Agregando estas modificaciones el código queda como: 1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.*; 4 5 public class Trigo extends JFrame implements ActionListener{ 6 private JButton b1; 7 private JTextField campo1; 8 private JTextField campo2; 9 private JLabel etq1; 10 private JLabel etq2; 11 private Panel panelEntrada, panelSalida;
  10. 10. 12 private JPanel panelDeLaVentana; 13 14 public Trigo(){ 15 //Creamos el boton 16 b1 = new JButton("seno"); 17 18 //Registramos a la ventana como oyente 19 b1.addActionListener(this); 20 21 //Creamos las etiquetas 22 etq1 = new JLabel("Angulo: "); 23 etq2 = new JLabel("Resultado: "); 24 25 //Creamos los campos de Texto 26 campo1 = new JTextField(); 27 campo2 = new JTextField(); 28 29 //Cambiamos la propiedades de los TextFields 30 campo2.setEditable(false); 31 campo2.setColumns(10); 32 campo2.setBackground(Color.lightGray); 33 campo1.setColumns(10); 34 35 //Creamos los paneles auxiliares 36 panelEntrada = new Panel(); 37 panelSalida = new Panel(); 38 39 //Obtenemos la referencia al panel principal 40 panelDeLaVentana = (JPanel)this.getContentPane(); 41 42 //Agregamos los componentes del panel de entrada 43 panelEntrada.add(campo1,BoxLayout.X_AXIS); 44 panelEntrada.add(etq1,BoxLayout.X_AXIS); 45 46 //Agregamos los componentes del panel de salida 47 panelSalida.add(campo2,BoxLayout.X_AXIS); 48 panelSalida.add(etq2,BoxLayout.X_AXIS); 49 50 //Agregamos todo al panel Principal 51 panelDeLaVentana.add(panelEntrada,BorderLayout.NORTH); 52 panelDeLaVentana.add(b1,BorderLayout.CENTER); 53 panelDeLaVentana.add(panelSalida,BorderLayout.SOUTH); 54 } 55 56 public void actionPerformed(ActionEvent e){ 57 double angulo = Double.parseDouble(campo1.getText()); 58 double resultado = Math.sin(angulo); 59 campo2.setText(resultado+""); 60 } 61 62 public static void main(String[] arg){ 63 Trigo miAplicacion = new Trigo(); 64 miAplicacion.setBounds(10,10,200,200); 65 miAplicacion.pack(); 66 miAplicacion.setVisible(true); 67 } 68 }
  11. 11. Es hora de probar la calculadora, pero no hay que olvidar que de acuerdo a la API, la función seno de la clase Math asume que el valor representa un ángulo en radianes.

×