Objetivo interfas a codigo

11
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,

description

 

Transcript of Objetivo interfas a codigo

Page 1: Objetivo interfas a codigo

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,

Page 2: Objetivo interfas a codigo

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.

Page 3: Objetivo interfas a codigo

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:

Page 4: Objetivo interfas a codigo

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);

Page 5: Objetivo interfas a codigo

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

Page 6: Objetivo interfas a codigo

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++;

Page 7: Objetivo interfas a codigo

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();

Page 8: Objetivo interfas a codigo

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

Page 9: Objetivo interfas a codigo

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;

Page 10: Objetivo interfas a codigo

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 }

Page 11: Objetivo interfas a codigo

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.