PR R O EP H I R BI O D D O U C IR CAPÍTULO 3 PR R O EP H I R BI O D D O U C IR Conceptos básicos de programación orientada a objetos ×ϐ que permite realizar una abstracción de la realidad, que se puede implementar en una aplicación de software ϐ problemas mediante el uso de un lenguaje de programación. El paradigma de orientación a objetos comprende una gran cantidad de conceptos que permite el desarrollo de aplicaciones robustas. 3.1 Paquete Un paquete es un contenedor de clases. Se utiliza para ordenar el código de forma consistente de acuerdo a los servicios implementados. Para que un código se encuentre contenido en un paquete es necesario agregar la siguiente sentencia. package MiPaquete; En donde “Mi Paquete” es el nombre del paquete que contendrá el código. Por otro lado, si se desea hacer uso de servicios implementados en otros paquetes se debe agregar el siguiente código. import OtroPaquete; Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Java contiene una gran cantidad de paquetes que proveen una gran cantidad de servicios. Algunos de estos paquetes se presentan en la Tabla 12. Tabla 12. Paquetes básicos del API de Java Paquete Descripción Provee clases necesarias para crear applets. java.awt Contiene todas las clases para crear ϐ ϐ imágenes. java.awt.color ϐ Ǥ java.awt.event Provee interfaces y clases para manejar ϐ Ǥ java.awt.font Provee interfaces y clases relacionadas con fuentes. java.awt.geom ʹϐ relacionadas con geometría de dos dimensiones. java.awt.image Provee interfaces y clases para crear y ϐ Ǥ java.awt.print Provee interfaces y clases para usar el API de impresión. java.beans Provee interfaces y clases para el desarrollo de beans, que hace referencia a componentes basados en JavaBeansTM architecture. java.beans.beancontext Provee interfaces y clases relacionadas con bean context. java.io Provee interfaces y clases para entrada y salida de datos serializables. PR R O EP H I R BI O D D O U C IR java.applet 24 Conceptos básicos de Programación Orientada a Objetos Provee clases fundamentales para el diseño del lenguaje de programación Java. java.math Provee clases para optimizar la precisión de entero aritmético (BigInteger) decimal aritmético (BigDecimal). java.net Provee clases para implementar aplicaciones de red. PR R O EP H I R BI O D D O U C IR java.lang java.rmi Provee interfaces y clases para servicios RMI. java.security Provee interfaces y clases para el framework de seguridad. java.sql Provee interfaces y clases para procesar datos almacenados en fuentes de datos como bases de datos. java.text Provee interfaces y clases para manipular texto, fechas, números y mensajes. java.util Contiene el framework de colecciones, modelo de eventos, servicios de fecha y tiempo, internacionalización y clases misceláneas. 3.2 Clase ϐ atributos y métodos. A través de una clase se implementa un concepto abstraído de la realidad. En este caso, los atributos hacen referencia a las características del concepto abstraído y los métodos hacen referencia a los servicios de dicho concepto. La sintaxis de la clase debe ser la siguiente: 25 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández public class MiClase{ 'H¿QLFLyQGHDWULEXWRV 'H¿QLFLyQGHPpWRGRV } En Java se debe seguir una buena práctica que consiste en implementar cada clase en un archivo independiente con extensión .java. Para el ejemplo anterior, el archivo debe denominarse MiClase.java. PR R O EP H I R BI O D D O U C IR 3.2.1 Atributos Los atributos hacen referencia a las características que se le incluyen a la clase. Estos atributos pueden ser declaraciones de tipos primitivos de datos o declaraciones de clases. 3.2.2 Visibilidad ϐ métodos. Los niveles de accesibilidad se dan por los siguientes términos: 1. private. Se puede acceder desde un método implementado desde la misma clase. 2. public. Se puede acceder desde un método implementado en cualquier clase. 3. protected. Se puede acceder desde un método implementado en una clase que herede la clase que contiene esta visibilidad y desde clases implementadas en el mismo paquete. 3.2.3 Métodos Los métodos hacen referencia a los servicios que se le incluyen a la clase. En estos métodos se implementa el código necesario del servicio. Un método contiene los siguientes elementos: 1. Visibilidad. Se debe establecer si el método es private, public o protected. 2. Retorno. Un método puede retornar información. Si el método no retorna información se debe colocar la palabra reservada “void”. 26 Conceptos básicos de Programación Orientada a Objetos El retorno puede ser un tipo primitivo de dato o una clase. Si un método tiene retorno, en la implementación del método, debe estar presente la palabra reservada “return”. 3. Ǥ ϐ ± Ǥ 4. Parámetros. Un método puede recibir de 0 a n parámetros. Un parámetro puede ser un tipo primitivo de dato o una declaración de una clase. Los parámetros deben estar separados por comas. PR R O EP H I R BI O D D O U C IR Cada método implementa un código que debe estar contenido entre “{” y “}”. La sintaxis de los métodos es la siguiente. //método publico sin retorno y sin parámetros public void miMetodo(){ instrucción 1; instrucción 2; .. instrucción n; } //método privado con retorno int y sin parámetros prívate int miMetodo(){ instrucción 1; instrucción 2; .. instrucción n; return valorInt; } //método privado con retorno int y con parámetros prívate int miMetodo(int parametro1, boolean parametro2, MiClase parametro3){ instrucción 1; instrucción 2; .. instrucción n; return valorInt; } 3.2.4 Encapsulamiento À ϐ propiedades propias de la clase deben tener visibilidad private. De esta forma se ofrece seguridad a la información depositada en dichos atributos. 27 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández 3.2.5 Apuntador this PR R O EP H I R BI O D D O U C IR El apuntador "this" permite acceder a los atributos y métodos de la clase. El uso del apuntador no es obligatorio, pero se recomienda usarlo como buena práctica. Es posible que el parámetro de un método tenga el mismo nombre que un atributo, en este caso el uso del apuntador this ϐ si está haciendo referencia al atributo o al parámetro del método. 3.3 Objeto Un objeto es la referencia e instancia de una clase. Al crear una referencia se asigna un espacio de memoria dinámica al objeto, pero no es utilizable. Al crear la instancia, el objeto es utilizable. La sintaxis de la referencia es la siguiente. MiClase m; Donde m es la referencia del objeto. La sintaxis de la instancia es: m = new MiClase(); Al hacer la instancia se puede acceder a los atributos y métodos públicos y protegidos si aplica, a través del objeto m. Otra sintaxis para realizar referencia e instancia en la misma línea de código es: MiClase m = new MiClase(); 3.4 Sentencia static Una clase puede tener atributos y/o métodos propios o no del objeto. La sentencia “staticdz ϐ ± que puedan ser accedidos sin requerir una instancia de la clase. Por otro lado, un atributo “static” toma el mismo valor para todos los objetos que sean instancia de la clase que lo contiene. Por ejemplo, la clase Math contiene el método “sin” el cual calcula el seno de un parámetro dado. 28 Conceptos básicos de Programación Orientada a Objetos Ejemplo: public class MiClase{ public static int miValor; PR R O EP H I R BI O D D O U C IR public static long factorial(long n) { long fact=1; for(int i=1; i<n; i++){ fact *= i; } return fact; } } En donde se puede hacer uso del método factorial de la siguiente forma. long valor = MiClase.factorial(5); También permite hacer uso del atributo miValor de la siguiente forma. MiClase c1 = new MiClase(); c1.miValor = 10; MiClase c2 = new MiClase(); MiClase c3 = new MiClase(); En el código anterior, el atributo miValor ͳͲ ͳǡ ʹ ͵ǡ ǡ el caso es en c1. 0AJPAJ?E=łJ=H ϐ constantes que no pueden cambiar su valor en tiempo de ejecución de la aplicación. La sintaxis es la siguiente: public class MiClase{ SXEOLF¿QDOVWDWLFLQWXQR SXEOLF¿QDOVWDWLFLQWGRV } 29 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Por ejemplo el atributo “PI” cuyo valor se encuentra implementado en la clase del API de Java Math, puede ser accedido sin requerir instancia de la clase Math y su valor es constante. H=OEł?=?EÉJ@AIÀPK@KO PR R O EP H I R BI O D D O U C IR ± ϐ siguientes: 1. Constructores. Un constructor es el primer método que se ejecuta al realizar la instancia de un objeto. Uno de los usos principales de un constructor es la inicialización de los atributos de la clase. El método constructor debe tener visibilidad pública y no posee retorno. La sintaxis es la siguiente: public class MiClase{ 'H¿QLFLyQGHDWULEXWRV prívate int atributo1; prívate int atributo2; 'H¿QLFLyQGHPpWRGRFRQVWUXFWRU public MiClase(){ this.atributo1=0; this.atributo1=0; } } 2. Consultores. Un consultor es el método que permite retornar el valor de un atributo con visibilidad private al aplicar el concepto de encapsulamiento. La sintaxis es la siguiente: public class MiClase{ 'H¿QLFLyQGHDWULEXWRV prívate int atributo1; prívate int atributo2; //Método constructor public MiClase(){ this.atributo1=0; this.atributo1=0; } 30 Conceptos básicos de Programación Orientada a Objetos //Método consultor public int getAtributo1() { return this.atributo1; } //Método consultor public int getAtributo2() { return this.atributo2; } PR R O EP H I R BI O D D O U C IR } 3. ϐ Ǥϐ ± valor a un atributo con visibilidad private al aplicar el concepto de encapsulamiento. La sintaxis es la siguiente: public class MiClase{ 'H¿QLFLyQGHDWULEXWRV prívate int atributo1; prívate int atributo2; //Método constructor public MiClase(){ this.atributo1=0; this.atributo1=0; } //Método consultor public int getAtributo1() { return this.atributo1; } //Método consultor public int getAtributo2() { return this.atributo2; } 0pWRGRPRGL¿FDGRU public void setAtributro1(int atributo1) { this.atributo1 = atributo1; } 0pWRGRPRGL¿FDGRU public void setAtributro2(int atributo2) { this.atributo2 = atributo2; } } 31 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández 4. Analizadores. Un analizador es el método que permite implementar la lógica del servicio del mismo, es decir, allí se implementan los algoritmos requeridos. La sintaxis es la siguiente: public class MiClase{ PR R O EP H I R BI O D D O U C IR 'H¿QLFLyQGHDWULEXWRV prívate int atributo1; prívate int atributo2; //Método constructor public MiClase(){ this.atributo1=0; this.atributo1=0; } //Método consultor public int getAtributo1() { return this.atributo1; } //Método consultor public int getAtributo2() { return this.atributo2; } 0pWRGRPRGL¿FDGRU public void setAtributro1(int atributo1) { this.atributo1 = atributo1; } 0pWRGRPRGL¿FDGRU public void setAtributro2(int atributo2) { this.atributo2 = atributo2; } //Método analizador public int calcularMayor() { if(this.atributo1 > this.atributo2){ return this.atributo1; }else{ return this.atributo2; } } } 32 Conceptos básicos de Programación Orientada a Objetos 0K>NA?=NC=@AIÀPK@KO PR R O EP H I R BI O D D O U C IR La sobrecarga de métodos es una característica que permite que varios métodos en una misma clase tengan el mismo nombre. La ϐ ± tiempo de ejecución, se debe a que estos deben poseer diferentes parámetros y/o retorno. La diferencia puede estar dada en el número de parámetros y/o en el tipo de los mismos. Por ejemplo se plantean los siguientes métodos sobrecargados. //Método sobrecargado 1. Sin parámetro y sin retorno. public void miMetodo(){ } //Método sobrecargado 2. Con parámetro y con retorno int. public int miMetodo(int parametro1){ } //Método sobrecargado 3. Con parámetros y con retorno boolean. public boolean miMetodo(int parametro1, int parametro2){ } //Método sobrecargado 4. Con parámetros diferentes a la sobrecarga 3 y con retorno boolean. public boolean miMetodo(int parametro1, long parametro2){ } 3.8 Recursividad La recursividad es la característica en la programación que permite hacer un llamado a un método desde el mismo método. À ϐ Ǥ equivale a una iteración en una estructura de repetición como el “while” o el “for”. Tiene la ventaja de utilizar casi los mismos recursos que en un proceso iterativo regular. Por otro lado, existen algoritmos que necesariamente deben ser implementados de forma recursiva como algoritmos fractales y árboles. 33 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Para aplicar el concepto de recursividad, el método debe necesariamente retornar un valor, recibir por parámetro al menos un valor, implementar una condición de ruptura del proceso recursivo e implementar una función recursiva. Por ejemplo, si se desea implementar el algoritmo del factorial se podría implementar el siguiente método para resolver el algoritmo: PR R O EP H I R BI O D D O U C IR public long factorial(long n) { long fact=1; for(int i=1; i<n; i++){ fact *= i; } return fact; } Entonces, suponiendo que nαͷǡͷ ǡ donde en cada iteración se presentan los siguientes resultados en las variables: 1. 2. 3. 4. 5. Primera iteración: fact=1*1=1 Segunda iteración: fact=1*2=2 ×ǣ αʹȗ͵α Cuarta iteración: fact=6*4=24 ×ǣ αʹͶȗͷαͳʹͲ También se puede hacer la implementación del algoritmo del factorial de forma recursiva. public long factorial(long n) { if(n==1 || n==0){ return 1; }else{ return n*factorial(n-1); } } ϐ es la siguiente: public long factorial(long n) { return (n==1)?1:n*factorial(n-1); } 34 Conceptos básicos de Programación Orientada a Objetos Entonces, suponiendo que nαͷǡ ͷ recursivas, en donde en cada llamada se presentan los siguientes resultados. ǣͷȗ ȋͶȌ ǣͶȗ ȋ͵Ȍ ǣ͵ȗ ȋʹȌ Cuarta llamada: retorna 2*factorial(1) Quinta llamada: retorna 1 PR R O EP H I R BI O D D O U C IR 1. 2. 3. 4. 5. Para hacer el primer llamado al método se puede considerar la siguiente sentencia: long f = factorial(5); En la Figura 1 se observa cómo cada llamada aporta a la consecución del resultado del algoritmo. Figura 1. Representación de funcionamiento de recursividad 3.9 Bajo acoplamiento Es la característica en el paradigma de orientación a objetos que indica que los diferentes subsistemas deben estar unidos de forma mínima. Esto indica, que las clases que se construyen deben ser lo 35 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández más reducidas, sin involucrar elementos que impliquen conceptos diferentes a los tratados en la clase. PR R O EP H I R BI O D D O U C IR Un ejemplo de bajo acoplamiento podría ser una memoria USB. Esta memoria es un sistema totalmente independiente al sistema del computador. Se conectan los dos sistemas a través del puerto USB y de forma automática, ambos sistemas quedan integrados. Además, esta operación se puede realizar mientras el computador se encuentre en funcionamiento. Así mismo es posible desconectar la memoria sin problemas. Un ejemplo de alto acoplamiento, con base en el anterior es el disco duro. Este se encuentra altamente acoplado, debido a que no se puede desconectar mientras el computador se encuentra en funcionamiento. Además, sin este sistema el computador no puede funcionar. Por otro lado, un ejemplo de bajo acoplamiento es la memoria USB, la cual se puede conectar y desconectar de forma simple y no afecta ni al computador ni a la memoria misma. HP=?KDAOEÉJ Es la característica en el paradigma de orientación a objetos que indica que, las propiedades y servicios de una clase deben ser consistentes con el concepto que abstrae dicha clase. Por ejemplo, si se tiene una clase Triángulo, esta clase podría contener los siguientes atributos: x ϐ × x Base x Altura Además podría tener servicios como: x Calcular Área x Calcular Perímetro En este ejemplo la clase Triángulo se encuentra altamente cohesionada ya que los atributos y métodos hacen referencia 36 Conceptos básicos de Programación Orientada a Objetos directa a características y comportamientos de concepto abstraído que es el triángulo. Si se incluye por ejemplo el método calcular volumen, esta clase estaría bajamente cohesionada, ya que un triángulo no posee volumen. Este método tendría que ser trasladado a la clase pirámide. PR R O EP H I R BI O D D O U C IR 3.11 Manejo de excepciones En el lenguaje Java, una “Exception” hace referencia a una condición anormal que se produce en tiempo de ejecución de la aplicación. Algunas excepciones son denominadas fatales, las cuales provocan ϐ × × ×Ǥ ǡ excepciones se generan por que falla la operación como consecuencia de un error de uso de la aplicación por parte del usuario. Para ilustrar el concepto, se presentan los siguientes ejemplos: x Si el usuario intenta abrir un archivo e ingresa de forma incorrecta la ruta del mismo, la aplicación presenta una excepción que debe controlarse para presentarle información de error de ruta del archivo al usuario. x Si el usuario desea ingresar un número para realizar una operación aritmética, pero erróneamente ingresa un carácter, la aplicación presenta una excepción de formato de número que debe controlarse para indicarle al usuario que no se puede realizar la operación aritmética. Las excepciones se representan mediante clases derivadas de la clase Throwable, sin embargo, las clases con las que se desarrolla, se derivan de la clase Exception que pertenece al paquete java.lang. 3.11.1 Estructura try, catch y ¿QDOO\ Las excepciones en Java deben ser capturadas mediante el uso de las estructuras "try", "catch" y "ϔ̺. En el bloque try se debe implementar el código del proceso que se desea ejecutar. En el 37 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR bloque catch se implementa el código alterno que se ejecutará en caso de que se presente una situación anormal o excepción en la ejecución del código implementado en el bloque try. Es posible tener varios bloques catch que resuelvan diferentes tipos de excepción. El bloque ϔ es opcional, pero en caso de implementarse, este se ejecutará independientemente, si se presenta o no excepción. Este se implementa posterior a la implementación del bloque try y del bloque catch. La sintaxis es la siguiente: public void miMetodo(){ .. try{ instrucción 1; instrucción 2; .. instrucción n; }catch(Exception e){ //Instrucciones del manejo de la excepcion `¿QDOO\^ //Instrucciones que se ejecutan en cualquiera de los dos casos } .. } 3.11.2 Sentencia throws En caso que el código de un método genere una "Exception", pero no se desee manejar dicha excepción, es posible enviar el manejo de la misma al método que hace el llamado. Este envío del manejo de la excepción se realiza mediante la inclusión de la sentencia "throws" seguida del nombre de la excepción posterior a los parámetros del método. Esta sentencia obliga a que el método que hace el llamado, implemente el manejo de la excepción a través del bloque "try catch" o envíe a su vez la excepción al método que hace el llamado a través de la sentencia "throws". La sintaxis es la siguiente. public void miMetodo()throws Exception{ .. } 38 Conceptos básicos de Programación Orientada a Objetos 3.11.3 Excepciones estándar del API de Java Las excepciones en Java se representan mediante dos tipos de clases derivadas de la clase Throwable que son Error y Exception. PR R O EP H I R BI O D D O U C IR La clase Error está relacionada con errores de compilación, errores del sistema o errores de la JVM. Estos errores son irrecuperables y no dependen del desarrollador. La clase Exception es la que debe tener en cuenta el desarrollador, debido a que de esta se derivan clases que manejan las excepciones que pueden ser controladas en tiempo de ejecución. Las clases derivadas de Exception más usuales son: 1. RuntimeException: contiene excepciones frecuentes en tiempo de ejecución de la aplicación. 2. IOException: contiene excepciones relacionadas con entrada y salida de datos. Las clases derivadas de Exception pueden pertenecer a distintos paquetes de Java. Algunas de ellas pertenecen a java.lang, otras a java.io y a otros paquetes. Por derivarse de la clase Throwable todos los tipos de excepciones pueden usar los métodos siguientes: 1. String getMessage(): extrae el mensaje asociado con la excepción. 2. String toString(): devuelve un String que describe la excepción. 3. void printStackTrace(): indica el método donde se lanzó la excepción. 39 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java ͖Ǥ ÀƤ Throwable 3.11.4 Creación de excepciones en Java En un proyecto es posible crear excepciones propias solo con heredar de la clase Exception o de una de sus clases derivadas. Las clases derivadas de Exception suelen tener dos constructores: 1. Un constructor sin argumentos. 2. Un constructor que recibe un String como argumento. En este Stringϐ × generada. Este mensaje debe enviarse a la clase Exception mediante la sentencia super(String). La sintaxis es la siguiente: 40 Conceptos básicos de Programación Orientada a Objetos class MiExcepcion extends Exception { public MiExcepcion() { // Constructor por defecto super(); } public MiExcepción(String s) { // Constructor con mensaje super(s); } } PR R O EP H I R BI O D D O U C IR 3.12 Ejercicios propuestos 1. Implemente una clase denominada Cuadrado que contenga un atributo privado, dos métodos constructores sobrecargados con y sin parámetros, métodos consultores, ± ϐ ± calculen el área y perímetro del cuadrado. 2. Implemente una clase denominada Triángulo que contenga un atributo privado, dos métodos constructores sobrecargados con y sin parámetros, métodos consultores, ± ϐ ± calculen el área y perímetro del triángulo. 3. Implemente una clase denominada Rectángulo que contenga un atributo privado, dos métodos constructores sobrecargados con y sin parámetros, métodos consultores, ± ϐ ± calculen el área y perímetro del rectángulo. 4. Implemente una clase denominada Operaciones, que contenga métodos estáticos que calculen el factorial de ïϐïǤ 41 PR R O EP H I R BI O D D O U C IR CAPÍTULO 4 PR R O EP H I R BI O D D O U C IR Clases de utilidad en Java Dentro del API de Java existe una gran colección de clases que son muy utilizadas en el desarrollo de aplicaciones. Entre las clases de utilidad de Java más utilizadas y conocidas están las siguientes: String, Integer, Double, Float, Long, Boolean, Math, Date, StringTokenizer yBigInteger. 4.1 Clase String La clase String está orientada al manejo de cadenas de caracteres y pertenece al paquete java.lang del API de Java. Los objetos que son instancia de la clase String, se pueden crear a partir de cadenas constantes también llamadas literales, las cuales deben estar contenidas entre comillas dobles. En la clase String, se puede asignar cadenas de las dos formas siguientes: String cadena1 = new String(“Hola”); String cadena2 = “Hola”; //Creación a través de constructor //Creación a través de literal ± ×±ϐ ǡ encontrar un texto entre comillas se crea automáticamente un objeto de la clase String. Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Tabla 13. Métodos principales de la clase String Retorno void Descripción String() Constructor que inicializa un objeto con una secuencia de caracteres vacía. String(char[] value) Constructor que crea un String inicializa un objeto con una secuencia de caracteres tipo char. PR R O EP H I R BI O D D O U C IR void Método charAt(int index) ϐ en la posición index. int compareTo(String anotherString) Compara dos cadenas de caracteres alfabéticamente. Ͳǡ negativo si la primera es menor o entero positivo si la primera es mayor. String concat(String str) Concatena la cadena del ϐ cadena. boolean Retorna true si la cadena contiene contains(CharSequence s) la secuencia tipo char del parámetro. char 44 boolean ȋϔȌ ϐ ϐ parámetro. boolean equals(Object anObject) Retorna verdadero si la cadena es igual al objeto del parámetro. int indexOf(String str) Retorna el índice de la primera ocurrencia de la cadena del parámetro. boolean isEmpty() Retorna verdadero si la longitud ͲǤ int length() Retorna la longitud de la cadena. Clases de utilidad en Java String String[] replace(char oldChar, char newChar) Retorna una nueva cadena reemplazando los caracteres del primer parámetro con el carácter del segundo parámetro. split(String regex) Retorna un conjunto de cadenas separadas por la cadena del parámetro. ȋϔȌ Retorna verdadero si el comienzo ϐ parámetro. String substring(int beginIndex) Retorna la subcadena desde el carácter del parámetro. String Retorna la subcadena desde el substring(int beginIndex, carácter del primer parámetro int endIndex) hasta el carácter del segundo parámetro. char[] toCharArray() Retorna el conjunto de caracteres de la cadena. String toLowerCase() Retorna la cadena en minúsculas. String toUpperCase() Retorna la cadena en mayúsculas. static String valueOf(char[] data) Convierte en cadena el conjunto de caracteres del parámetro. static String valueOf(double d) Convierte en cadena el dato del parámetro. static String ȋϔȌ Convierte en cadena el dato del parámetro. static String valueOf(int i) Convierte en cadena el dato del parámetro. static String valueOf(long l) Convierte en cadena el dato del parámetro. static String valueOf(Object obj) Convierte en cadena el objeto del parámetro. PR R O EP H I R BI O D D O U C IR boolean 45 Ejemplo de uso del método length y charAt public class EjemplosString { PR R O EP H I R BI O D D O U C IR public static void main(String[] args) { String cadena=”Hola Mundo”; char caracter; System.out.println(“La cadena tiene “+cadena.length()+ ”caracteres”); for(int i=0; i<cadena.length(); i++){ caracter=cadena.charAt(i); System.out.println(“El caracter en la posición “+ i+” es: “+caracter); } } } Salida estándar La cadena tiene 10 caracteres El caracter en la posición 0 es: H El caracter en la posición 1 es: o El caracter en la posición 2 es: l El caracter en la posición 3 es: a El caracter en la posición 4 es: El caracter en la posición 5 es: M El caracter en la posición 6 es: u El caracter en la posición 7 es: n El caracter en la posición 8 es: d El caracter en la posición 9 es: o Ejemplo de uso del método concat public class EjemplosString { public static void main(String[] args) { String cadena1=”Hola”; String cadena2=”Mundo”; System.out.println(“La cadena 1 es: “+cadena1); System.out.println(“La cadena 2 es: “+cadena2); System.out.println(“El texto concatenado es: “+ cadena1.concat(cadena2)); } } Salida estándar La cadena 1 es: Hola La cadena 2 es: Mundo El texto concatenado es: HolaMundo Ejemplo de uso del método replace public class EjemplosString { public static void main(String[] args) { String cadena=”Este es el texto original”; System.out.println(“La cadena es: “+cadena); 6\VWHPRXWSULQWOQ ³/DFDGHQDPRGL¿FDGDHV³ cadena.replace(‘e’, ‘?’)); } PR R O EP H I R BI O D D O U C IR } Salida estándar La cadena es: Este es el texto original /DFDGHQDPRGL¿FDGDHV(VW""V"OW"[WRRULJLQDO Ejemplo de uso del método split public class EjemplosString { public static void main(String[] args) { String cadena=”Hola planeta tierra”; String cadenas[]=cadena.split(“ “); for(int i=0; i<cadenas.length; i++){ System.out.println(“La cadena “+i+” es: “+cadenas[i]); } } } Salida estándar La cadena 0 es: Hola La cadena 1 es: planeta La cadena 2 es: tierra Ejemplo de uso del método substring public class EjemplosString { public static void main(String[] args) { String cadena=”Hola planeta tierra”; System.out.println(“La cadena es: “+cadena); System.out.println(“La sub cadena del caracter 2 al 10 es: “+cadena.substring(2, 10)); } } Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Salida estándar La cadena es: Hola planeta tierra La subcadena del caracter 2 al 10 es: la plane Ejemplo de uso de los métodos toUpperCase y toLowerCase public class EjemplosString { PR R O EP H I R BI O D D O U C IR public static void main(String[] args) { String cadena=”Hola Mundo”; System.out.println(“El texto normal es: “+cadena); System.out.println(“El texto en mayúsculas es: “+ cadena.toUpperCase()); System.out.println(“El texto en minúsculas es: “+ cadena.toLowerCase()); } } Salida estándar El texto normal es: Hola Mundo El texto en mayúsculas es: HOLA MUNDO El texto en minúsculas es: hola mundo 4.2 Clase Integer La clase Integer permite convertir un tipo primitivo de dato int a objeto Integer. La clase Integer pertenece al paquete java.lang del API de Java y hereda de la clase java.lang.Number. Provee métodos para realizar diferentes tipos de conversiones relacionados con el tipo primitivo de dato int. Tabla 14. Métodos principales de la clase Integer Retorno 48 Método void Integer(int value) void Integer(String s) Descripción Constructor que inicializa un objeto con un dato primitivo. Constructor que inicializa un objeto con una cadena de caracteres. Esta cadena debe contener un número entero. Clases de utilidad en Java compareTo(Integer anotherInteger) Compara dos objetos Integer numéricamente. double doubleValue() Retorna el valor del Integer en tipo primitivo double. boolean equals(Object obj) Compara el Integer con el objeto del parámetro. ϔ ϔȋȌ Retorna el valor del Integer en tipo primitivo ϔǤ int intValue() Retorna el valor del Integer en tipo primitivo int. long longValue() Retorna el valor del Integer en tipo primitivo long. static int parseInt(String s) Convierte la cadena de caracteres del parámetro en tipo primitivo int. short shortValue() Retorna el valor del Integer en tipo primitivo short. static String toBinaryString(int i) Retorna el número del parámetro en su correspondiente cantidad binaria en una cadena de caracteres. toHexString(int i) Retorna el número del parámetro en su correspondiente cantidad hexadecimal en una cadena de caracteres. static String toOctalString(int i) Retorna el número del parámetro en su correspondiente cantidad octal en una cadena de caracteres. String toString() Retorna el valor del Integer en una cadena de caracteres. static Integer valueOf(int i) Retorna el número del parámetro en un objeto Integer. static Integer valueOf(String s) Retorna la cadena del parámetro en un objeto Integer. PR R O EP H I R BI O D D O U C IR int static String 49 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Nota: las clases Byte, Short, Long, Double y Float tienen las mismas características de la clase Integer, diferenciándose por el tamaño del dato en el caso de Byte, Short y Long; y por la capacidad de número real en el caso de Double y Float. Ejemplo de uso de los métodos intValue y ϔ public class EjemplosInteger { PR R O EP H I R BI O D D O U C IR public static void main(String[] args) { Integer dato=new Integer(“10”); System.out.println(“El int es: “+dato.intValue()); 6\VWHPRXWSULQWOQ ³(OÀRDWHV³GDWRÀRDW9DOXH } } Salida estándar El int es: 10 (OÀRDWHV Ejemplo de uso de los métodos toBinaryString, toOctalString y toHexString public class EjemplosInteger { public static void main(String[] args) { int decimal=1000; String binario=Integer.toBinaryString(decimal); String octal=Integer.toOctalString(decimal); String hexa=Integer.toHexString(decimal); System.out.println(“El número decimal es: “+decimal); System.out.println(“El número binario es: “+binario); System.out.println(“El número octal es: “+octal); System.out.println(“El número hexadecimal es: “+hexa); } } Salida estándar El número decimal es: 1000 El número binario es: 1111101000 El número octal es: 1750 El número hexadecimal es: 3e8 50 Clases de utilidad en Java 4.3 Clase Boolean La clase Boolean permite convertir un tipo primitivo de dato boolean a objeto boolean. La clase booleana pertenece al paquete java.lang del API de Java. PR R O EP H I R BI O D D O U C IR Provee métodos para realizar diferentes tipos de conversiones relacionados con el tipo primitivo de dato booleano. Tabla 15. Métodos principales de la clase Boolean Retorno Método Descripción Boolean(boolean value) Constructor que inicializa un objeto con un dato primitivo. void Boolean(String s) Constructor que inicializa un objeto con una cadena de caracteres. Si la cadena y es igual al texto “true” el valor es verdadero. boolean booleanValue() Retorna el valor del Boolean en tipo primitivo boolean. int compareTo(Boolean b) Compara el valor del Boolean con el valor del parámetro. static boolean parseBoolean(String s) Convierte la cadena de caracteres del parámetro en tipo primitivo boolean. String toString() Retorna el valor del Boolean en una cadena de caracteres. static Boolean valueOf(boolean b) Retorna el valor booleano del parámetro en un objeto booleano. static Boolean valueOf(boolean b) Retorna la cadena del parámetro en un objeto booleano. void 51 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández 4.4 Clase Math PR R O EP H I R BI O D D O U C IR La clase Math contiene métodos para utilizar operaciones numéricas básicas y funciones trigonométricas. La clase Math pertenece al paquete java.lang del API de Java. La clase Math ϐ “ϔ” que indica que no puede tener instancia, de tal forma que sus atributos y métodos son “static”. Tabla 16. Atributos de la clase Math Tipo Atributo Descripción static double E Retorna la base de logaritmo natural que ʹǤͳͺʹͺͳͺʹͺͶͷͻͲͶͷ static double PI Retorna el número pi que es equivalente al perímetro de la circunferencia dividido el Ǥ͵ǤͳͶͳͷͻʹͷ͵ͷͺͻͻ͵ Tabla 17. Métodos principales de la clase Math 52 Retorno Método Descripción static double abs(double a) Retorna el número absoluto del parámetro double. ϔ ȋϔȌ Retorna el número absoluto del parámetro ϔ. static int abs(int a) Retorna el número absoluto del parámetro int. static long abs(long a) Retorna el número absoluto del parámetro long. static double acos(double a) Retorna el arco coseno del valor del parámetro. El ángulo ͲǤͲpi. static double asin(double a) Retorna el arco seno del valor del parámetro. El ángulo retornado está entre –pi/2 y pi/2. Clases de utilidad en Java atan(double a) static double cbrt(double a) Retorna la raíz cubica del valor del parámetro. static double cos(double a) Retorna el coseno del ángulo del parámetro. static double cosh(double x) Retorna el coseno hiperbólico del ángulo del parámetro. static double exp(double a) Retorna el número de Eurler basado de la potencia del parámetro. static double log(double a) Retorna el logaritmo natural del valor del parámetro. static double log10(double a) ͳͲ valor del parámetro. static double max(double a, double b) Retorna el número mayor entre los parámetros double. ϔ ȋϔǡϔ b) Retorna el número mayor entre los parámetros ϔ. static int max(int a, int b) Retorna el número mayor entre los parámetros int. static long max(long a, long b) Retorna el número mayor entre los parámetros long. static double min(double a, double b) Retorna el número menor entre los parámetros double. ϔ ȋϔǡϔȌ Retorna el número menor entre los parámetros ϔ. static int min(int a, int b) Retorna el número menor entre los parámetros int. PR R O EP H I R BI O D D O U C IR static double Retorna el arco tangente del valor del parámetro. El ángulo retornado está entre –pi/2 y pi/2. 53 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández min(long a, long b) Retorna el número menor entre los parámetros long. static double pow(double a, double b) Retorna la potencia del primer parámetro elevado al segundo parámetro. static double random() Retorna un número double ͲǤͲͳǤͲǤ static long round(double a) Retorna el número long más cercano del parámetro double. static int ȋϔȌ Retorna el número int más cercano del parámetro ϔ. static double sin(double a) Retorna el seno del ángulo del parámetro. static double sinh(double a) Retorna el seno hiperbólico del ángulo del parámetro. static double sqrt(double a) Retorna la raíz cuadrada del valor del parámetro. static double tan(double a) Retorna la tangente del ángulo del parámetro. static double tanh(double a) Retorna la tangente hiperbólica del ángulo del parámetro. static double toDegrees(double angrad) Convierte un ángulo de radianes a grados. static double toRadians (double angdeg) Convierte un ángulo de grados a radianes. PR R O EP H I R BI O D D O U C IR static long 54 Clases de utilidad en Java Ejemplo de uso de los métodos cbrt, sqrt y pow public class EjemplosMath { PR R O EP H I R BI O D D O U C IR public static void main(String[] args) { double dato=144; double raizCuadrada = Math.sqrt(dato); System.out.println(“La raíz cuadrada de: “+dato+ ” es: “+raizCuadrada); double raizCubica = Math.cbrt(dato); System.out.println(“La raíz cúbica de: “+dato+ ” es: “+raizCubica); double base=5; double exponente=4; double potencia=Math.pow(base, exponente); System.out.println(“La potencia de “+base+ ” ^ “+exponente+” es: “+potencia); } } Salida estándar La raíz cuadrada de: 144.0 es: 12.0 La raíz cúbica de: 144.0 es: 5.241482788417793 La potencia de 5.0 ^ 4.0 es: 625.0 Ejemplo de uso del atributo PI y de los métodos sin, cos, round y toRadians public class EjemplosMath{ public static void main(String[] args) { double seno; double coseno; for(int i=0;i<=360;i+=90){ seno=Math.round(Math.sin(i*Math.PI/180)); System.out.println(“El seno de “+i+” usando PI/180 es: “+ seno); seno=Math.round(Math.sin(Math.toRadians(i))); System.out.println(“El seno de “+i+” usando toRadians es: “+ seno); coseno=Math.round(Math.cos(i*Math.PI/180)); System.out.println(“El coseno de “+i+” usando PI/180 es: “+ coseno); coseno=Math.round(Math.cos(Math.toRadians(i))); System.out.println(“El coseno de “+i+” usando toRadians es: “+ coseno); } } } 55 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Salida estándar PR R O EP H I R BI O D D O U C IR El seno de 0 usando PI/180 es: 0.0 El seno de 0 usando toRadians es: 0.0 El coseno de 0 usando PI/180 es: 1.0 El coseno de 0 usando toRadians es: 1.0 El seno de 90 usando PI/180 es: 1.0 El seno de 90 usando toRadians es: 1.0 El coseno de 90 usando PI/180 es: 0.0 El coseno de 90 usando toRadians es: 0.0 El seno de 180 usando PI/180 es: 0.0 El seno de 180 usando toRadians es: 0.0 El coseno de 180 usando PI/180 es: -1.0 El coseno de 180 usando toRadians es: -1.0 El seno de 270 usando PI/180 es: -1.0 El seno de 270 usando toRadians es: -1.0 El coseno de 270 usando PI/180 es: 0.0 El coseno de 270 usando toRadians es: 0.0 El seno de 360 usando PI/180 es: 0.0 El seno de 360 usando toRadians es: 0.0 El coseno de 360 usando PI/180 es: 1.0 El coseno de 360 usando toRadians es: 1.0 4.5 Clase Date La clase Date ϐ precisión en milisegundos. Adicionalmente, la clase Date permite el uso del formato Universal Coordinated Time, UTC. Por otro lado, ϐ ± Greenwich Mean Time, GMT, que es equivalente a Universal Time, UT. GMT es el nombre estándar y UT Àϐ Ǥ diferencia entre UT y UTC es que, UTC está basado en un reloj atómico y UT está basado en un reloj astronómico. Las fechas en Java comienzan en el valor “standar based time” llamado “epochdz ͳͳͻͲǡͲͲ ͲGMT. La clase Date posee métodos que permiten la manipulación de fechas. La clase Date pertenece al paquete java.util del API de Java. 56 Clases de utilidad en Java Tabla 18. Métodos principales de la clase Date Retorno Método Date() void Date(long date) Constructor que inicializa la fecha en el milisegundo más cercano a la fecha del sistema. Constructor que inicializa la fecha en milisegundos del parámetro a partir del “epoch”. PR R O EP H I R BI O D D O U C IR void Descripción boolean after(Date when) Retorna verdadero si la fecha esta después de la fecha del parámetro. boolean before(Date when) Retorna verdadero si la fecha esta antes de la fecha del parámetro. int compareTo(Date anotherDate) Compara la fecha con la del ǤͲ son iguales. boolean equals(Object obj) Retorna verdadero si la fecha es igual a la del objeto del parámetro. long getTime() Retorna la fecha en milisegundos a partir del “epoch”. void setTime(long time) Asigna la fecha en milisegundos a partir del “epoch”. String toString() Retorna la fecha en una cadena de caracteres. Ejemplo de uso del método toString import java.util.Date; public class EjemplosDate { public static void main(String[] args) { Date fecha=new Date(); String fechaActual=fecha.toString(); System.out.println(“La fecha actual es: “+fechaActual); } } 57 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Salida estándar La fecha actual es: Thu Jul 01 02:11:54 GMT 2010 4.6 Clase StringTokenizer PR R O EP H I R BI O D D O U C IR La clase StringTokenizer permite en una aplicación romper una cadena en unidades denominadas token. Una cadena se puede romper generando un token a través de un delimitador. Si este delimitador no ϐ ǡ Ǥ StringTokenizer pertenece al paquete java.lang del API de Java. Tabla 19. Métodos principales de la clase StringTokenizer Retorno void void void int 58 Método Descripción Constructor que inicializa la cadena StringTokenizer(String de caracteres con el parámetro. El delimitador por defecto será un str) espacio. Constructor que inicializa la StringTokenizer(String cadena de caracteres con el primer parámetro y el delimitador con el str, String delim) segundo parámetro. Constructor que inicializa la StringTokenizer(String cadena de caracteres con el primer parámetro y el delimitador con str, String delim, el segundo parámetro. Si el tercer boolean returnDelims) parámetro es true, cada token incluye el delimitador. Retorna el número de tokens en la countTokens() cadena. boolean hasMoreTokens () String nextToken() String nextToken(String delim) Retorna verdadero si hay más tokens disponibles en la cadena. Retorna el siguiente token de la cadena. Retorna el siguiente token de la cadena con base en el delimitador ϐ Ǥ Clases de utilidad en Java Ejemplo de uso de los métodos hasMoreTokens y nextToken import java.util.StringTokenizer; public class EjemplosStringTokenizer { PR R O EP H I R BI O D D O U C IR public static void main(String[] args) { String token; String texto1=”Este es un texto de prueba”; StringTokenizer tokenizer1=new StringTokenizer(texto1); while(tokenizer1.hasMoreTokens()){ token=tokenizer1.nextToken(); System.out.println(“El token es: “+token); } String texto2=”Este;es;otro;texto;de;prueba”; StringTokenizer tokenizer2=new StringTokenizer(texto2,”;”); while(tokenizer2.hasMoreTokens()){ token=tokenizer2.nextToken(); System.out.println(“El token con delimitador ; es: “+token); } } } Salida estándar El token es: Este El token es: es El token es: un El token es: texto El token es: de El token es: prueba El token con delimitador ; es: Este El token con delimitador ; es: es El token con delimitador ; es: otro El token con delimitador ; es: texto El token con delimitador ; es: de El token con delimitador ; es: prueba 4.7 Clase BigInteger La clase BigInteger permite en una aplicación manejar datos ± ϐǤ Considerando que el tipo primitivo de datos “long” tiene un valor ͻǤʹʹ͵Ǥ͵ʹǤͲ͵ǤͺͷͶǤͷǤͺͲǡ realizar operaciones con datos enteros mayores a este valor, se 59 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández hace estrictamente necesario el uso de la clase BigInteger. La clase BigInteger pertenece al paquete java.math del API de Java. Tabla 20. Métodos principales de la clase BigInteger Retorno Método Descripción Constructor que inicializa el BigInteger con el valor de la cadena de caracteres del parámetro. Retorna el valor absoluto del BigInteger. BigInteger(String val) BigInteger abs() BigInteger add(BigInteger val) Retorna la suma del BigInteger con el parámetro. and(BigInteger val) Retorna el resultado de la operación lógica AND del BigInteger con el parámetro. PR R O EP H I R BI O D D O U C IR void BigInteger int int BigInteger BigInteger[] 60 Retorna el número de bits del BigInteger. compareTo(BigInteger Compara el BigInteger con el val) parámetro. Retorna la división del divide(BigInteger val) BigInteger con el parámetro. Retorna el cociente y residuo de divideAndRemainder la división del BigInteger con el (BigInteger val) parámetro. bitCount() double doubleValue() Convierte el BigInteger a double. ϔ ϔȋȌ Convierte el BigInteger a ϔǤ int intValue() Convierte el BigInteger a int. long longValue() Convierte el BigInteger a long. BigInteger max(BigInteger val) BigInteger min(BigInteger val) BigInteger mod(BigInteger m) Retorna el mayor entre el BigInteger y el parámetro. Retorna el menor entre el BigInteger y el parámetro. Retorna el residuo de la división del BigInteger con el parámetro. Clases de utilidad en Java multiply(BigInteger val) BigInteger not() BigInteger or(BigInteger val) Retorna la multiplicación del BigInteger con el parámetro. Retorna el resultado de la operación lógica NOT del BigInteger. Retorna el resultado de la operación lógica OR del BigInteger con el parámetro. Retorna la potenciación del BigInteger con el parámetro. PR R O EP H I R BI O D D O U C IR BigInteger BigInteger pow(int exponent) BigInteger subtract (BigInteger val) String toString() static BigInteger valueOf(long val) BigInteger xor(BigInteger val) Retorna la resta del BigInteger con el parámetro. Retorna el BigInteger en una cadena de caracteres Retorna un BigInteger con el valor del parámetro. Retorna el resultado de la operación lógica XOR del BigInteger con el parámetro. Ejemplo de uso del método pow import java.math.BigInteger; public class EjemplosBigInteger { public static void main(String[] args) { long potLong; int base=10; for(int exp=15;exp<=25;exp++){ potLong=(long)Math.pow(base, exp); System.out.println(“La potenciación usando long de “+ base+”^”+exp+” es:”+potLong); } BigInteger potBigInteger=new BigInteger(String. valueOf(base)); for(int exp=15;exp<=25;exp++){ System.out.println(“La potenciación usando BigInteger de “+ base+”^”+exp+” es: “+potBigInteger.pow(exp)); } } } 61 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Salida estándar PR R O EP H I R BI O D D O U C IR La potenciación usando long de 10^15 es:1000000000000000 La potenciación usando long de 10^16 es:10000000000000000 La potenciación usando long de 10^17 es:100000000000000000 La potenciación usando long de 10^18 es:1000000000000000000 La potenciación usando long de 10^19 es:9223372036854775807 La potenciación usando long de 10^20 es:9223372036854775807 La potenciación usando long de 10^21 es:9223372036854775807 La potenciación usando long de 10^22 es:9223372036854775807 La potenciación usando long de 10^23 es:9223372036854775807 La potenciación usando long de 10^24 es:9223372036854775807 La potenciación usando long de 10^25 es:9223372036854775807 La potenciación usando BigInteger de 10^15 es: 1000000000000000 La potenciación usando BigInteger de 10^16 es: 10000000000000000 La potenciación usando BigInteger de 10^17 es: 100000000000000000 La potenciación usando BigInteger de 10^18 es: 1000000000000000000 La potenciación usando BigInteger de 10^19 es: 10000000000000000000 La potenciación usando BigInteger de 10^20 es: 100000000000000000000 La potenciación usando BigInteger de 10^21 es: 1000000000000000000000 La potenciación usando BigInteger de 10^22 es: 10000000000000000000000 La potenciación usando BigInteger de 10^23 es: 100000000000000000000000 La potenciación usando BigInteger de 10^24 es: 1000000000000000000000000 La potenciación usando BigInteger de 10^25 es: 10000000000000000000000000 4.8 Ejercicios propuestos 1. Implemente mediante la clase String, una aplicación que cuente el número de vocales de un texto. 2. Implemente mediante la clase BigInteger, una aplicación que emule una calculadora aritmética y lógica. Esta calculadora debe permitir operaciones con números muy grandes. 3. Implemente una aplicación que permita convertir números decimales a su equivalencia en cualquier base. 62 CAPÍTULO 8 PR R O EP H I R BI O D D O U C IR %ANAJ?E=ULKHEIKNłOIK 8.1 Herencia ϐ ǡ ϐ × previamente desarrollado, generando una jerarquía de clases dentro de la aplicación. Entonces, si una clase se deriva de otra, esta hereda sus atributos y métodos. La clase derivada puede añadir nuevos ±Ȁϐ±Ǥ Para que un atributo y método puedan ser heredados es necesario que su visibilidad sea “protected”. En Java, a diferencia de otros lenguajes orientados a objetos, una clase solo puede derivar de una única clase, con lo cual, no es posible realizar herencia múltiple con base en clases. Sin embargo, es posible “simular” la herencia múltiple con base en las interfaces. Un ejemplo del concepto de herencia puede ser considerando, los miembros de una institución de educación. La institución está conformada por personas, pero cada persona tiene un rol dentro de la institución, que podría ser de empleado, estudiante o egresado. Así ǡÀ ϐ ×ǡ ± administrativo. De académico se puede derivar, decano, coordinador y docente. De administrativo se puede derivar de acuerdo a la cantidad de departamentos de la institución. La representación de herencia del caso anteriormente expuesto en lenguaje de modelado es la siguiente: Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 7. Jerarquía de herencia de personal académico ϐ± Ǥ Se puede considerar una clase denominada FiguraGeometrica, del cual heredan las clases Cuadrado, Círculo, Triángulo y Rectángulo. En este caso, la clase FiguraGeometrica, poseería un atributo que puede ser llamado valor1. Este atributo es heredado por las clases Cuadrado, Círculo, Triángulo y Rectángulo. Sin embargo, las clases Rectángulo y Triángulo requieren dos valores. Esto indica que deben incluirse como atributos de cada una de estas clases. Por otro lado, la clase FiguraGeometrica puede implementar los métodos consultores ϐ ǡ que la heredan. Así mismo, de la clase Cuadrado, es posible heredar la clase Cubo. De la clase Triángulo es posible heredar la clase Pirámide y Cono. 120 Herencia y polimorfismo PR R O EP H I R BI O D D O U C IR De la clase Círculo es posible heredar la clase Esfera y Cilindro. La representación de herencia del caso anteriormente expuesto, en lenguaje de modelado, es la siguiente: ͜Ǥ À Ƥ± Ǥ 8.1.1 Sentencia H[WHQGV La sentencia “extends” permite implementar el concepto de herencia. Se incluye para que una clase herede de otra clase. Por ejemplo, en el caso de jerarquía de herencia de personal académico, debe existir una clase persona y una clase estudiante. Al implementar la clase estudiante se le debe incluir la sentencia extends para que herede de la clase persona. La sintaxis es la siguiente: public class Persona{ ... } public class Estudiante extends Persona{ ... } 121 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Una vez incluida la sentencia extends, la clase Estudiante tiene acceso a atributos y métodos protegidos de la clase Persona. 8.1.2 Sentencia super PR R O EP H I R BI O D D O U C IR La sentencia “super” es utilizada para acceder a métodos implementados en la clase superior en el concepto de herencia. Esta sentencia es comúnmente utilizada para acceder al constructor de la clase superior desde el constructor de la clase inferior. Por ejemplo, en el caso de jerarquía de herencia de personal académico debe existir una clase persona ϐ ×ǡǡ apellido y correo, y una clase Estudiante que puede acceder a estos atributos pero que adicionalmente, tiene atributos como código y facultad. Al implementar el constructor de la clase estudiante para asignar los valores de los atributos, se puede hacer un llamado al constructor de la clase persona ϐ en dicha clase. La sintaxis es la siguiente: public class Persona{ protected int id protected String nombre protected String apellido protected String correo public Persona(int id, String nombre, String apellido, String correo){ this.id=id; this.nombre=nombre; this.apellido=apellido; this.correo=correo; } } public class Estudiante extends Persona{ private int codigo private String facultad public Estudiante(int id, String nombre, String apellido, String correo, int codigo, String facultad){ 122 Herencia y polimorfismo super(id, nombre, apellido, correo); this.codigo=codigo; this.facultad=facultad; } } PR R O EP H I R BI O D D O U C IR En el ejemplo anterior, el constructor de la clase estudiante, hace un llamado al constructor de la clase persona asignando los valores a los ÀϐǤ 8.1.3 Sobre-escritura de métodos La sobre-escritura de métodos es una característica que se presenta en el concepto de herencia, que consiste en implementar un método en la clase superior e inferior en la jerarquía de herencia. Por ejemplo, considerando las clases cuadrado y cubo de la jerarquía ϐ ± ͻǡ crear un método getArea, tanto para la clase cuadrado como para la clase cubo. Entonces, si se crea una referencia de la clase cuadrado, dependiendo de la instancia del objeto que se crea que puede ser de cuadrado o cubo, se accede al método implementado en cuadrado o en cubo, respectivamente. Figura 9. Jerarquía de herencia de Cuadrado y Cubo 123 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández La implementación de esta jerarquía es la siguiente: Clase Cuadrado SDFNDJH¿JXUDV*HRPHWULFDV public class Cuadrado { protected int valor1; PR R O EP H I R BI O D D O U C IR public Cuadrado(double valor1) { this.valor1=valor1; } public double getArea() { return Math.pow(this.valor1, 2); } } Clase Cubo SDFNDJH¿JXUDV*HRPHWULFDV public class Cubo extends Cuadrado { public Cubo(double valor1) { super(valor1); } public double getArea() { return Math.pow(this.valor1, 3); } } En la implementación anterior, sobre escribe el método getArea debido a que el área del cuadrado es diferente al área del cubo. Java ϐ ± Ǧ ejecución. 8.1.4 Clases abstractas Una clase abstracta es aquella que no puede ser instanciada, es decir, no se pueden crear objetos de esta clase. Se usa para permitir que 124 Herencia y polimorfismo otras clases hereden de esta proporcionando atributos y métodos que son comunes de las clases heredadas. La sintaxis para la creación de una clase abstracta es la siguiente: public abstract class FiguraGeometrica { ... } PR R O EP H I R BI O D D O U C IR Una clase abstracta puede contener atributos y métodos. Sin embargo, adicionalmente puede contener métodos abstractos, los cuales son ϐǤϐ heredan de la clase abstracta, implementen de forma obligatoria dichos métodos abstractos. À ϐ ± ǡ implementación de la clase FiguraGeometrica es la siguiente: SDFNDJH¿JXUDV*HRPHWULFDV public abstract class FiguraGeometrica { protected double valor1; public FiguraGeometrica(double valor1) { super(); this.valor1 = valor1; } public double getValor1() { return valor1; } public void setValor1(double valor1) { this.valor1 = valor1; } public abstract double getArea(); public abstract double getPerimetro(); } De esta forma, las clases que hereden de la clase FiguraGeometrica pueden acceder al atributo valor1, a los métodos getValor1 y setValor1 y deben implementar los métodos getArea y getPerimetro. 125 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Cuando se implementa una clase abstracta es importante tener en cuenta que, la clase no debe ser instanciada. Por ejemplo, en el caso de FiguraGeometrica, no se debe crear un objeto instancia de esta clase debido a que FiguraGeometrica en la realidad, actúa como una generalización, es decir, para realizar cálculos sobre una ϐ ±ϐ ǡ Ǥ ǡ ϐ ± ϐ ± obligatoriamente, implementar las clases que hereden de la clase Ǥǡ ϐ tiene área y tiene perímetro. Por consiguiente, estos servicios deben ϐ ×± Ǥ De esta manera la implementación de las clases que heredan de FiguraGeometrica es la siguiente: Clase Cuadrado SDFNDJH¿JXUDV*HRPHWULFDV public class Cuadrado extends FiguraGeometrica { public Cuadrado(double valor1) { super(valor1); } @Override public double getArea() { return Math.pow(this.valor1, 2); } @Override public double getPerimetro() { return this.valor1*4; } } Clase Círculo SDFNDJH¿JXUDV*HRPHWULFDV public class Circulo extends FiguraGeometrica { 126 Herencia y polimorfismo public Circulo(double valor1) { super(valor1); } @Override public double getArea() { return Math.PI*Math.pow(this.valor1, 2); } PR R O EP H I R BI O D D O U C IR @Override public double getPerimetro() { return Math.PI*this.valor1; } } Clase Triángulo SDFNDJH¿JXUDV*HRPHWULFDV public class Triangulo extends FiguraGeometrica { private double valor2; public Triangulo(double valor1, double valor2) { super(valor1); this.valor2 = valor2; } public double getValor2() { return valor2; } public void setValor2(double valor2) { this.valor2 = valor2; } @Override public double getArea() { return (this.valor1*this.valor2)/2; } @Override public double getPerimetro() { return this.valor1 + (2 * Math.sqrt((Math.pow( this.valor1, 2)+Math.pow(this.valor2, 2)))); } } 127 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Clase Rectángulo SDFNDJH¿JXUDV*HRPHWULFDV public class Rectangulo extends FiguraGeometrica { private double valor2; PR R O EP H I R BI O D D O U C IR public Rectangulo(double valor1, double valor2) { super(valor1); this.valor2 = valor2; } public double getValor2() { return valor2; } public void setValor2(double valor2) { this.valor2 = valor2; } @Override public double getArea() { return this.valor1*this.valor2; } @Override public double getPerimetro() { return 2*this.valor1 + 2*this.valor2; } } 8.1.5 Interfaces Una interfaz es un tipo especial de clase que permite realizar un conjunto de declaraciones de métodos sin implementación. En una ±ϐ ǡÀ public, static y ϔǢ deben siempre inicializarse en la declaración. ϐ ǡ debe incluir la sentencia “implements” la cual indica que implementa la interfaz. La sintaxis es la siguiente: public interface MiInterfaz { ... } public class MiClase implements MiInterfaz { ... } 128 Herencia y polimorfismo ± ϐ tipo de conducta para las clases que implementan dicha interfaz. Todas las clases que colocan en funcionamiento una determinada interfaz, están obligadas a proporcionar una implementación de los métodos declarados en la interfaz adquiriendo un comportamiento. PR R O EP H I R BI O D D O U C IR Una clase puede implementar una o varias interfaces. Para indicar que una clase implementa más de una interfaz, se ponen los nombres de las interfaces separados por comas, posterior a incluir la sentencia “implements”. La sintaxis es la siguiente: public class MiClase implements MiInterfaz1, MiInterfaz2, MiInterfazN { ... } Un ejemplo del uso de interfaces con base en el modelo de herencia ϐ ± Ǥ ǡ ϐ À Ǥ Para ello, se crea una interfaz denominada FiguraDibujable que ± ϐ ϐǤ Círculo e implemente FiguraDibujable y una clase que herede de Rectángulo e implemente FiguraDibujable. Clase FiguraGeometrica SDFNDJH¿JXUDV*HRPHWULFDV public abstract class FiguraGeometrica { protected double valor1; public FiguraGeometrica(double valor1) { super(); this.valor1 = valor1; } public double getValor1() { return valor1; } 129 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández public void setValor1(double valor1) { this.valor1 = valor1; } public abstract double getArea(); public abstract double getPerimetro(); } PR R O EP H I R BI O D D O U C IR Interfaz FiguraDibujable SDFNDJH¿JXUDV*HRPHWULFDV import java.awt.Graphics; public interface FiguraDibujable { public void setCoordenadas(int x, int y); public void dibujar2D(Graphics g); } Clase Círculo SDFNDJH¿JXUDV*HRPHWULFDV public class Circulo extends FiguraGeometrica { public Circulo(double valor1) { super(valor1); } @Override public double getArea() { return Math.PI*Math.pow(this.valor1, 2); } @Override public double getPerimetro() { return Math.PI*this.valor1; } } Clase CírculoDibujable SDFNDJH¿JXUDV*HRPHWULFDV import java.awt.Graphics; 130 Herencia y polimorfismo public class CirculoDibujable extends Circulo implements FiguraDibujable { private int x; private int y; PR R O EP H I R BI O D D O U C IR public CirculoDibujable(double valor1, int x, int y) { super(valor1); this.x = x; this.y = y; } @Override public void setCoordenadas(int x, int y) { this.x=x; this.y=y; } @Override public void dibujar2D(Graphics g) { g.drawOval(this.x, this.y, (int)this.valor1, ( int)this.valor1); } } Clase Rectángulo pDFNDJH¿JXUDV*HRPHWULFDV public class Rectangulo extends FiguraGeometrica { protected double valor2; public Rectangulo(double valor1, double valor2) { super(valor1); this.valor2 = valor2; } public double getValor2() { return valor2; } public void setValor2(double valor2) { this.valor2 = valor2; } @Override public double getArea() { return this.valor1*this.valor2; } 131 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández @Override public double getPerimetro() { return 2*this.valor1 + 2*this.valor2; } } Clase RectánguloDibujable PR R O EP H I R BI O D D O U C IR SDFNDJH¿JXUDV*HRPHWULFDV import java.awt.Graphics; public class RectanguloDibujable extends Rectangulo implements FiguraDibujable { private int x; private int y; public RectanguloDibujable(double valor1, double valor2, int x, int y) { super(valor1, valor2); this.x = x; this.y = y; } @Override public void setCoordenadas(int x, int y) { this.x=x; this.y=y; } @Override public void dibujar2D(Graphics g) { g.drawRect(this.x, this.y, (int)this.valor1, ( int)this.valor2); } } -KHEIKNłOIK ϐ À × ǡϐ de ejecución basado en una jerarquía de herencia. De esta forma, es posible generar una relación de vinculación denominada “binding”. ϐ ǡ abstractas e interfaces. 132 Herencia y polimorfismo ϐ servicios en tiempo de ejecución sin necesidad de implementar diferentes referencias a objetos. Esta característica provee una gran ϐ × ×Ǥ PR R O EP H I R BI O D D O U C IR Por ejemplo, considerando la jerarquía de herencia de Figuras Geométricas ϐ ϐǤ Figura 10. Jerarquía de herencia de Figuras Geométricas ͳͲ FiguraGeometrica de la siguiente forma: )LJXUD*HRPHWULFD¿JXUD A la referencia ϔ se le puede generar instancia de cualquiera de las clases que derivan de ella de la siguiente forma: 133 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández ¿JXUD QHZ&LUFXOR ¿JXUD QHZ&XDGUDGR ¿JXUD QHZ5HFWDQJXOR ¿JXUD QHZ7ULDQJXOR ¿JXUD QHZ&XER PR R O EP H I R BI O D D O U C IR En la primera línea, el objeto ϔ tiene la forma de círculo, de tal forma que si se accede al método getArea, se ejecuta el método implementado en círculo. En la segunda línea, el objeto ϔ tiene la forma de cuadrado, de tal forma que si se accede al método getArea, se ejecuta el método implementado en cuadrado. En la tercer línea, el objeto ϔ tiene la forma de rectángulo, de tal forma que si se accede al método getArea, se ejecuta el método implementado en rectángulo. En la cuarta línea, el objeto ϔ tiene la forma de triángulo, de tal forma que si se accede al método getArea, se ejecuta el método implementado en triángulo. En la quinta línea, el objeto ϔ tiene la forma de cubo, de tal forma que si se accede al método getArea, se ejecuta el método implementado en cubo. La siguiente implementación del modelo presentado demuestra en × ϐǤ Clase FiguraGeometrica SDFNDJH¿JXUDV*HRPHWULFDV public abstract class FiguraGeometrica { protected double valor1; public FiguraGeometrica(double valor1) { super(); this.valor1 = valor1; } 134 Herencia y polimorfismo public double getValor1() { return valor1; } public void setValor1(double valor1) { this.valor1 = valor1; } PR R O EP H I R BI O D D O U C IR public abstract double getArea(); public abstract double getPerimetro(); } Clase Círculo SDFNDJH¿JXUDV*HRPHWULFDV public class Circulo extends FiguraGeometrica { public Circulo(double valor1) { super(valor1); } @Override public double getArea() { return Math.PI*Math.pow(this.valor1, 2); } @Override public double getPerimetro() { return Math.PI*this.valor1; } } Clase Cuadrado SDFNDJH¿JXUDV*HRPHWULFDV public class Cuadrado extends FiguraGeometrica { public Cuadrado(double valor1) { super(valor1); } @Override public double getArea() { 135 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández return Math.pow(this.valor1, 2); } @Override public double getPerimetro() { return this.valor1*4; } } PR R O EP H I R BI O D D O U C IR Clase Rectángulo SDFNDJH¿JXUDV*HRPHWULFDV public class Rectangulo extends FiguraGeometrica { protected double valor2; public Rectangulo(double valor1, double valor2) { super(valor1); this.valor2 = valor2; } public double getValor2() { return valor2; } public void setValor2(double valor2) { this.valor2 = valor2; } @Override public double getArea() { return this.valor1*this.valor2; } @Override public double getPerimetro() { return 2*this.valor1 + 2*this.valor2; } } Clase Triángulo SDFNDJH¿JXUDV*HRPHWULFDV public class Triangulo extends FiguraGeometrica { private double valor2; 136 Herencia y polimorfismo public Triangulo(double valor1, double valor2) { super(valor1); this.valor2 = valor2; } public double getValor2() { return valor2; } PR R O EP H I R BI O D D O U C IR public void setValor2(double valor2) { this.valor2 = valor2; } @Override public double getArea() { return (this.valor1*this.valor2)/2; } @Override public double getPerimetro() { return this.valor1 + (2 * Math.sqrt(( Math.pow(this.valor1, 2)+Math.pow(this.valor2, 2)))); } } Clase Cubo SDFNDJH¿JXUDV*HRPHWULFDV public class Cubo extends Cuadrado { public Cubo(double valor1) { super(valor1); } public double getArea() { return Math.pow(this.valor1, 3); } } Clase Principal SDFNDJH¿JXUDV*HRPHWULFDV public class Principal { 137 Programación Orientada a Objetos usando Java public static void main(String[] args) { )LJXUD*HRPHWULFD¿JXUD ¿JXUD QHZ&LUFXOR 6\VWHPRXWSULQWOQ ¿JXUDJHW&ODVV 6\VWHPRXWSULQWOQ ³$UHD³¿JXUDJHW$UHD 6\VWHPRXWSULQWOQ ³3HULPHWUR³¿JXUDJHW3HULPHWUR ¿JXUD QHZ&XDGUDGR 6\VWHPRXWSULQWOQ ¿JXUDJHW&ODVV 6\VWHPRXWSULQWOQ ³$UHD³¿JXUDJHW$UHD 6\VWHPRXWSULQWOQ ³3HULPHWUR³¿JXUDJHW3HULPHWUR ¿JXUD QHZ5HFWDQJXOR 6\VWHPRXWSULQWOQ ¿JXUDJHW&ODVV 6\VWHPRXWSULQWOQ ³$UHD³¿JXUDJHW$UHD 6\VWHPRXWSULQWOQ ³3HULPHWUR³¿JXUDJHW3HULPHWUR ¿JXUD QHZ7ULDQJXOR 6\VWHPRXWSULQWOQ ¿JXUDJHW&ODVV 6\VWHPRXWSULQWOQ ³$UHD³¿JXUDJHW$UHD 6\VWHPRXWSULQWOQ ³3HULPHWUR³¿JXUDJHW3HULPHWUR ¿JXUD QHZ&XER 6\VWHPRXWSULQWOQ ¿JXUDJHW&ODVV 6\VWHPRXWSULQWOQ ³$UHD³¿JXUDJHW$UHD 6\VWHPRXWSULQWOQ ³3HULPHWUR³¿JXUDJHW3HULPHWUR } PR R O EP H I R BI O D D O U C IR Héctor Arturo Flórez Fernández } Salida estándar class FigurasGeometricas.Circulo Area: 78.53981633974483 Perimetro: 15.707963267948966 class FigurasGeometricas.Cuadrado Area: 25.0 Perimetro: 20.0 class FigurasGeometricas.Rectangulo Area: 10.0 Perimetro: 14.0 class FigurasGeometricas.Triangulo Area: 5.0 Perimetro: 15.770329614269007 class FigurasGeometricas.Cubo Area: 125.0 Perimetro: 20.0 En la implementación de la clase Principal se puede apreciar que el objeto ϔ cambia de forma cada vez que se hace una nueva 138 Herencia y polimorfismo instancia. Así mismo, en cada instancia se accede a la implementación del método de la clase instanciada. PR R O EP H I R BI O D D O U C IR El último caso realiza la instancia de la clase Cubo, en donde esta clase no tiene implementado el método getPerimetro. Para este caso, en el llamado a este método, se accede al método getPerimetro implementado en la clase superior que es Cuadrado. 8.3 Ejercicios propuestos 1. Implemente una aplicación que a partir de un modelo de herencia represente animales con las siguientes ϐ Ǥ a. Mamífero i. Canino 1. Perro 2. Lobo ii. Felino 1. 2. Tigre b. Ovíparo i. Ave 1. Águila 2. Paloma ii. Pez 1. Trucha 2. Salmón 2. Con base en el ejercicio anterior implemente una interfaz que contenga métodos de comportamiento de los animales descritos. 139 PR R O EP H I R BI O D D O U C IR CAPÍTULO 9 PR R O EP H I R BI O D D O U C IR Documentación con Javadoc Javadoc genera documentación API en formato HTML, para el paquete ϐ Ǥ± indicar una serie de paquetes o clases Java con los que se desea generar la documentación. Javadoc genera un archivo con extensión “.html” por cada clase .java y paquete que encuentra. También genera la jerarquía de clases en un archivo denominado tree.html y un índice con todos los miembros que ha detectado en un archivo denominado AllNames.html. Para generar la documentación se debe utilizar la aplicación Javadoc que se encuentra en la ruta: [jdk]/bin/javadoc [nombrePaquete]|[archivos.java] En donde la ruta [jdk] representa la ubicación donde se encuentra instalada la máquina virtual de Java. El parámetro [nombrePaquete] hace referencia al paquete al que se le aplicara Javadoc y el parámetro [archivo.java] hace referencia a la clase a la que se le aplicará Javadoc. ϐ generar con Javadoc a través de doclets. Un doclet es un programa Java escrito utilizando el Java Doclet APIǡ ϐ y formato de la salida que ha de generar Javadoc. Se pueden escribir doclets para generar cualquier tipo de salida de texto, ya sea HTML, SGML, RTF o MIF. Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Cuando no se indica ningún doclet Àϐ À ǡ Javadoc utilizará el doclet estándar que genera una salida HTML. !K?QIAJP=?EÉJ@A?É@ECKBQAJPA PR R O EP H I R BI O D D O U C IR Para generar el Javadoc no es necesario hacer comentarios a todas las líneas de código. Lo único estrictamente necesario es comentar la clase y cada uno de sus métodos. Como Javadoc comprueba automáticamente clases, interfaces, métodos y atributos; se puede añadir documentación adicional a través de comentarios de documentación en el código fuente. Javadoc reconoce marcas especiales cuando recorre los comentarios de documentación. Estas marcas permiten autogenerar una documentación completa y bien formateada del API a partir del código fuente. Las marcas comienzan siempre con el signo @. Estas marcas deben situarse al principio de la línea y todas las marcas con el mismo nombre deben agruparse juntas dentro del comentario de documentación. Solamente se indicarán las más representativas agrupadas por clases, métodos y atributos. Para documentar clases e interfaces se cuenta con las siguientes etiquetas: @version 1.0 Incluye información de versión de la clase. Un comentario de documentación puede incluir más de una marca @version. @author Hector Florez Incluye información de versión de la clase. Un comentario de documentación puede incluir más de una marca @author. @see java.lang.String 142 Documentación con Javadoc Incluye un enlace a la documentación de una clase a la clase en la zona “See Also”. Un comentario de documentación puede incluir más de una marca @see. @see java.lang.String#valueOf PR R O EP H I R BI O D D O U C IR El carácter # separa el nombre de una clase del nombre de uno de sus atributos o métodos. Para documentar métodos se cuenta con las siguientes etiquetas: @param parametro descripcion Incluye información de parámetro del método. Cada método debe incluir tantas etiquetas como parámetros. @return descripcion Incluye información de retorno del método. @exception nombredelaclase de Excepcion descripcion Incluye información de manejo de excepción que puede ser lanzada por el método. La excepción estará enlazada con su clase en la documentación. 9.2 Resultados de Javadoc ×ϐ± en el capítulo anterior se puede generar la siguiente documentación: Clase FiguraGeometrica SDFNDJH¿JXUDV*HRPHWULFDV /** * Clase abstracta que hereda a Circulo, Cuadrado, Triangulo y Rectangulo * @version 1.0 143 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández * @author Hector Florez */ public abstract class FiguraGeometrica { protected double valor1; PR R O EP H I R BI O D D O U C IR /** &RQVWUXFWRU$VLJQDXQYDORUDOD¿JXUDJHRPHWULFD * @param valor1 Recibe valor del atributo a traves del constructor */ public FiguraGeometrica(double valor1) { super(); this.valor1 = valor1; } /** * Metodo consultor del atributo valor1 * @return Retorna el valor del atributo a traves del metodo consultor */ public double getValor1() { return valor1; } /** 0HWRGRPRGL¿FDGRUGHODWULEXWRYDORU * @param valor1 Recibe valor del atributo a traves del PHWRGRPRGL¿FDGRU */ public void setValor1(double valor1) { this.valor1 = valor1; } /** 0HWRGRDEVWUDFWRTXHGH¿QHHOVHUYLFLRFDOFXODUDUHD #UHWXUQ5HWRUQDHODUHDGHOD¿JXUD */ public abstract double getArea(); /** 0HWRGRDEVWUDFWRTXHGH¿QHHOVHUYLFLRFDOFXODUSHULPHWUR #UHWXUQ5HWRUQDHOSHULPHWURGHOD¿JXUD */ public abstract double getPerimetro(); } 144 Documentación con Javadoc Clase Círculo SDFNDJH¿JXUDV*HRPHWULFDV PR R O EP H I R BI O D D O U C IR /** * Clase que provee servicios para el TAD Circulo * @version 1.0 * @author Hector Florez * @see Math */ public class Circulo extends FiguraGeometrica { /** * Constructor. Asigna un valor al circulo. * Llama al constructor de FiguraGeometrica * @param valor1 Recibe valor del atributo a traves del constructor */ public Circulo(double valor1) { super(valor1); } /** * Metodo sobre-escrito que calcula el area del circulo * @return Retorna el area del circulo */ @Override public double getArea() { return Math.PI*Math.pow(this.valor1, 2); } /** * Metodo sobre-escrito que calcula el perimetro del circulo * @return Retorna el perimetro del circulo */ @Override public double getPerimetro() { return Math.PI*this.valor1; } } Documentando todas las clases del paquete FigurasGeometricas, al aplicar Javadoc, se obtienen los siguientes resultados: 145 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 11. Javadoc. Jerarquía de paquetes 146 PR R O EP H I R BI O D D O U C IR Documentación con Javadoc Figura 12. Javadoc. Documentación de clase abstracta 147 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 13. Javadoc. Documentación de clase que hereda de clase abstracta 148 PR R O EP H I R BI O D D O U C IR Documentación con Javadoc Figura 14. Javadoc. Documentación de métodos de clase 149 PR R O EP H I R BI O D D O U C IR CAPÍTULO 10 PR R O EP H I R BI O D D O U C IR Desarrollo orientado a arquitecturas Desarrollar una aplicación basada en una arquitectura, permitirá a la aplicación tener características fundamentales del paradigma de orientación a objetos como son bajo acoplamiento, alta cohesión y escalabilidad. ϐ Ǥ especializar en servicios enfocados a resolver algún comportamiento o característica de la aplicación. Por ejemplo, si se tiene una aplicación ϐ ǡ interfaz deben estar separadas por medio de una capa de las clases que tienen otro objetivo en la aplicación como es el almacenamiento de datos o comunicación de información. 10.1 Arquitectura de tres capas La arquitectura de tres capas es una técnica en el desarrollo de aplicaciones de software que tiene como objetivo la separación de la lógica del negocio de la presentación y de la persistencia. Una de las principales ventajas se obtiene con el bajo acoplamiento de las aplicaciones debido a que esta característica, permite fácilmente realizar cambios en los servicios sin tener que revisar todos los componentes de la aplicación. Además, esta técnica permite distribuir el trabajo de los desarrolladores por niveles, en donde cada equipo de desarrollo puede hacer uso de los componentes desarrollados por Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández otro equipo sin necesidad de conocer el desarrollo, solo conociendo los resultados de los servicios. PR R O EP H I R BI O D D O U C IR La división en componentes reduce la complejidad, permite la reutilización de código agilizando el proceso de desarrollo del producto de software. Por otro lado, esta estrategia, permite hacer correcto uso de las metodologías de desarrollo de software. Particularmente, la metodología ȋ ϔ Ȍ se adapta cómodamente a la arquitectura, permitiendo facilidad en los procesos de desarrollo de la aplicación. La arquitectura de tres capas se basa en el siguiente modelo. Figura 15. Arquitectura de tres capas La capa de presentación exhibe la aplicación al usuario, le muestra la información y captura la información del usuario. Esta capa se comunica con la capa de lógica de negocio por medio de objetos que se denominan “Object value”. La capa de lógica de negocio es donde se desarrollan los algoritmos propios de la aplicación. En esta capa se implementa la lógica obtenida por el análisis de requerimientos del proyecto. Esta capa provee servicios a la capa de presentación, recibiendo como parámetros la información que el usuario entrega a la aplicación. Esta capa se comunica con la capa de persistencia por medio de objetos que se denominan “Object value”. La capa de persistencia es donde se almacenan los datos y se realiza las operaciones para manipular dichos datos. Estos datos pueden 152 Desarrollo orientado a arquitecturas PR R O EP H I R BI O D D O U C IR encontrarse en cualquier tipo de sistema que almacene información en disco duro como archivos y bases de datos. Esta capa recibe solicitudes de almacenamiento o recuperación de información desde la capa de la lógica del negocio. Entonces esta capa es la encargada de abrir archivos o crear conexiones a bases de datos. Las conexiones a bases de datos deben realizarse a través de componentes denominados “JDBC (Java Data Base Connector)”. La capa de persistencia usa el JDBC para manipular la información de la base de datos. La arquitectura de tres capas tiene una característica adicional que es la facilidad de aplicación de patrones de desarrollo de software. ǡϐ realizar escalabilidad, portabilidad y usabilidad, entre otros. ϐ a la aplicación de forma transparente para los procesos contenidos en ella. Por ejemplo, si se tiene una aplicación de escritorio y se desea ϐ × webǡ ϐ presentación dejando intacta las otras capas. En este caso, la nueva capa de presentación hace uso de la capa de lógica accediendo a los servicios que esta capa presta. Otro ejemplo consiste en la posibilidad de cambiar de motor de base de datos. En este caso, bastaría con ϐ × JDBC ϐ todo el proyecto. Se pueden plantear dos formas simples para aplicar una arquitectura de tres capas a un proyecto, dependiendo de su tamaño y complejidad. La primera forma, consiste en crear tres paquetes que harán referencia a cada capa. En cada uno de estos paquetes se implementan las clases necesarias para proveer los servicios requeridos. En la capa de presentación debe estar ubicado el método mainǡ ϐ la aplicación inicie su ejecución en esta capa. Esta implementación es válida para proyectos pequeños con pocos requerimientos. La Figura 16 presenta la distribución de clases en un proyecto orientado a esta arquitectura utilizando la herramienta de desarrollo eclipse IDE. 153 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 16. Implementación basada en paquetes de arquitectura de tres capas La segunda forma consiste en crear tres proyectos, en donde cada proyecto hará referencia a cada capa. En cada uno de estos proyectos se implementan las clases necesarias para proveer los servicios requeridos. En el proyecto que hace referencia a la capa de presentación debe estar ubicado el método mainǡ ϐ aplicación inicie su ejecución en esta capa. Esta implementación es válida para cualquier tipo de proyectos. ϐ Presentación para que pueda acceder al proyecto Lógica y el proyecto Lógica para que pueda acceder al proyecto Persistencia. En eclipse IDE este procedimiento se realiza a través de la opción “ϔ” que presenta ϐ × ͳǤ 154 PR R O EP H I R BI O D D O U C IR Desarrollo orientado a arquitecturas ͕͛ǤƤ ×Build Path En la pestaña Projects se adiciona el proyecto correspondiente. ͳͺ × orientado a esta arquitectura utilizando la herramienta de desarrollo eclipse IDE. 155 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 18. Implementación basada en proyectos de arquitectura de tres capas 10.2 Arquitectura multicapa Una arquitectura multicapa se basa en la arquitectura de tres capas. Con frecuencia, cada capa de la arquitectura de tres capas se puede componer de varias capas. Se puede considerar las siguientes situaciones: x Si se tiene una aplicación web, la capa de presentación, podría contener componentes para el uso de AJAX (Asincronous Javascript And Xml ), de esta forma, la capa de presentación 156 Desarrollo orientado a arquitecturas se compondría de las clases que hacen parte de la lógica de presentación, más una capa adicional AJAX que contendría las clases para proveer estos servicios. x Si se tiene una capa de lógica de negocio, en donde se requiere encriptación, se puede crear una nueva capa que contenga ϐÀǤ PR R O EP H I R BI O D D O U C IR x Si se desea implementar el patrón ORM (Object Relationship Mapping) en la capa de persistencia, es posible dividir esta capa en una capa que contenga las clases necesarias para realizar la conexión a las bases de datos y otra capa que contenga clases de mapeo relacional de objetos. Figura 19. Arquitectura multicapa usando AJAX y ORM. 157 PR R O EP H I R BI O D D O U C IR CAPÍTULO 11 PR R O EP H I R BI O D D O U C IR &JPANB=VCN¹ł?=@A usuario (GUI) Swing es un componente de Java que se ocupa de construir interfaces gráficas de usuario. Swing es la evolución de AWT que ×ͳǤͲǤSwing se incorporó a Java en la versión 1.2. En la versión 1.6 de Java, todos los desarrollos de interfaz gráfica se realizan mediante Swing, debido a la potencialidad que este componente ofrece. De esta forma, todos los componentes que pertenecen a Swing pertenecen al paquete javax.swing. La siguiente figura presenta la jerarquía de herencia de los componentes que posee Swing. Las clases en cursiva hacen referencia a clases abstractas. ʹͲ Swing heredan de la clase Component que pertenece al paquete AWT. Esta clase posee una gran cantidad de métodos que son utilizados por todas las clases del paquete Swing. Estos métodos permiten proporcionar a todas las clases una gran cantidad de servicios. Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 20. Jerarquía de herencia de los componentes de Swing 160 Interfaz gráfica de usuario (GUI) Tabla 32. Métodos principales de la clase Component Retorno Método Descripción add(PopupMenu popup) Adiciona un menú emergente al componente. void addComponent Listener (ComponentListener l) Agrega al componente un objeto para manipulación de eventos. PR R O EP H I R BI O D D O U C IR void Agrega al componente un objeto para manipulación de eventos de foco. void addFocusListener (FocusListener l) void Agrega al componente un addKeyListener (KeyListener objeto para manipulación de l) eventos de teclado. void addMouseListener (MouseListener l) Agrega al componente un objeto para manipulación de eventos de los botones del mouse. void addMouseMotion Listener (MouseMotion Listener l) Agrega al componente un objeto para manipulación de eventos de movimiento del mouse. void addMouseMotionListener (MouseMotionListener l) Agrega al componente un objeto para manipulación de eventos de movimiento del mouse. ϔ getAlignmentX() Retorna un valor que indica la alineación en el eje X. ϔ getAlignmentY() Retorna un valor que indica la alineación en el eje Y. Color getBackground() Retorna el color de fondo del componente. Font getFont() Retorna la fuente de texto del componente. 161 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández getHeight() Retorna el alto en píxeles del componente. Dimension getMaximumSize() Retorna el tamaño máximo del componente. Dimension getMinimumSize () Retorna el tamaño mínimo del componente. String getName() Retorna el nombre del componente. Dimension getPreferredSize() Retorna el tamaño preferido del componente. Este hace referencia al tamaño inicial. Dimension getSize() Retorna el tamaño actual del componente. int getWidth() Retorna el ancho del componente. int getX() Retorna la coordenada X de la posición del componente. int getY() Retorna la coordenada Y de la posición del componente. boolean hasFocus() Retorna verdadero si el componente posee el foco en tiempo de ejecución de la aplicación. boolean isEnabled() Retorna verdadero si el componente se encuentra habilitado. boolean isVisible() Retorna verdadero si el componente esta visible. void paint(Graphics g) Permite pintar en el componente. void remove(MenuComponent popup) Retira el menú emergente ϐ Ǥ void setBackground(Color c) Coloca color de fondo al componente. PR R O EP H I R BI O D D O U C IR int 162 Interfaz gráfica de usuario (GUI) void setEnabled(boolean b) Habilita o inhabilita el componente. void setFont(Font f) Coloca fuente de texto al componente. void setName(String name) Coloca nombre al componente. void setSize(int width, int height) Coloca tamaño al componente. void setVisible(boolean b) Muestra u oculta el componente. PR R O EP H I R BI O D D O U C IR void Coloca el componente en la posición determinada por 1.1.1. setBounds(int x, int las coordenadas x,y con el y, int width, int height) tamaño determinado por el ancho y alto. 11.2 Contenedores ϐ ϐ Ǥ × un contenedor para que a través de este pueda iniciarse la aplicación. 11.2.1 JFrame Un JFrame es un contenedor que se comporta como una ventana, ϐÀ Ǥ estar dadas por el tamaño, color y posición, entre otras. Para implementar un JFrame es necesario crear una clase que herede de la clase JFrame del paquete javax.swing. La sintaxis para crear un JFrame es la siguiente: SDFNDJHLQWHUID]*UD¿FD import javax.swing.JFrame; 163 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández import javax.swing.WindowConstants; public class MiJFrame extends JFrame { public static void main(String[] args) { MiJFrame frame = new MiJFrame(); frame.setVisible(true); } PR R O EP H I R BI O D D O U C IR public MiJFrame() { initGUI(); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Mi JFrame”); setSize(400, 300); } } Al ejecutar la aplicación se despliega el JFrame ÓͶͲͲ À ͵ͲͲÀÀǣJFrame. El método setDefaultCloseOperation ϐ JFrame para que al dar clic en la X superior derecha, el JFrame se cierre. El JFrame se presenta como se muestra en la Figura 21. Figura 21. JFrame 164 Interfaz gráfica de usuario (GUI) 11.2.2 -,QWHUQDO)UDPH Un JInternalFrame es un contenedor que se comporta como una ventana interna, es decir, una ventana que se puede abrir solo dentro de un JFrame. PR R O EP H I R BI O D D O U C IR A través de un JInternalFrame es posible implementar aplicaciones MDI (Multiple Interface Document), debido a que es posible abrir varios JInternalFrame dentro de un JFrame, en donde cada uno de ellos provee funcionalidades independientes a la aplicación. Para que un JFrame pueda contener un JInternalFrame es necesario tener dentro del JFrame otro contenedor especial denominado JDesktopPane. Este contenedor se adiciona al JFrame con la siguiente sintaxis: JDesktopPane desktopPane = new JDesktopPane(); getContentPane().add(desktopPane); Desde el JFrame debe crearse un instancia al JInternalFrame. Para adicionar la instancia al JFrame se debe hacer a través del JDesktopPane con la siguiente sintaxis: FInterno frame = new FInterno(); desktopPane.add(frame); La siguiente implementación presenta la creación de una aplicación simple basada en JInternalFrame. Clase FPrincipal SDFNDJHLQWHUID]*UD¿FDLQWHUQDO)UDPH import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private JDesktopPane desktopPane; 165 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } PR R O EP H I R BI O D D O U C IR public FPrincipal() { initGUI(); FInterno1 frame1 = new FInterno1(); this.desktopPane.add(frame1); FInterno2 frame2 = new FInterno2(); this.desktopPane.add(frame2); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Principal”); { this.desktopPane = new JDesktopPane(); getContentPane().add(desktopPane); } setSize(400, 300); } } Clase FInterno1 SDFNDJHLQWHUID]*UD¿FDLQWHUQDO)UDPH import javax.swing.JInternalFrame; public class FInterno1 extends JInternalFrame { public FInterno1() { initGUI(); } private void initGUI() { setSize(200, 100); setVisible(true); setTitle(“Frame Interno 1”); } } 166 Interfaz gráfica de usuario (GUI) Clase FInterno2 SDFNDJHLQWHUID]*UD¿FDLQWHUQDO)UDPH import javax.swing.JInternalFrame; public class FInterno2 extends JInternalFrame { PR R O EP H I R BI O D D O U C IR public FInterno2() { initGUI(); } private void initGUI() { setSize(200, 100); setVisible(true); setTitle(“Frame Interno 2”); } } Al ejecutar la aplicación el resultado es como se muestra en la Figura 22. Figura 22. JInternalFrame 167 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández -3DQHO PR R O EP H I R BI O D D O U C IR Un JPanel es un contenedor que tiene muchas aplicaciones. Dentro de las aplicaciones más comunes están, el permitir agregar ϐ forma determinada. Otra aplicación común es utilizar el JPanel como ϐ Ǥ ± À acuerdo al uso que se le esté dando. La implementación de un JPanel en un JFrame es la siguiente: SDFNDJHLQWHUID]*UD¿FDSDQHO import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.WindowConstants; import javax.swing.border.TitledBorder; public class FPrincipal extends JFrame { private JPanel panel; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( this.setTitle(“Frame Principal”); { panel = new JPanel(); panel.setBorder(new TitledBorder(“Titulo del Panel”)); getContentPane().add(panel); } setSize(400, 300); } } ʹ͵Ǥ 168 PR R O EP H I R BI O D D O U C IR Interfaz gráfica de usuario (GUI) Figura 23. JPanel -7DEEHG3DQH Un JTabbedPane es un contenedor de pestañas, en donde cada pestana se debe construir con un JPanel. La forma de agregar un panel, a un panel de pestañas, es haciendo uso del método addTab. La sintaxis para crear un panel de pestañas y para crear paneles que se agreguen a las pestañas es la siguiente: JTabbedPane panelPestanas = new JTabbedPane(); JPanel panel1 = new JPanel(); panelPestanas.addTab(“Pestaña 1”, panel1); JPanel panel2 = new JPanel(); panelPestanas.addTab(“Pestaña 2”, new ImageIcon(“img/ informacion.png”),panel2); En el código anterior se puede apreciar que el primer panel se agregó con un método sobrecargado de dos parámetros, que contienen el texto de la pestaña y el panel correspondiente. El segundo panel se agregó con un método sobrecargado de tres parámetros que incluye adicionalmente, un ícono que se envía con la ruta donde se encuentra dicha imagen. La imagen debe encontrarse en una carpeta dentro del 169 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández proyecto. La imagen puede ser de extensiones jpg, png, gif o ico. Se recomienda utilizar imágenes con resolución de 16 x 16 píxeles. La implementación de un JTabbedPane en un JFrame es la siguiente. SDFNDJHLQWHUID]*UD¿FDWDEEHG3DQH PR R O EP H I R BI O D D O U C IR import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private JPanel panel1; private JPanel panel2; private JTabbedPane panelPestanas; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); { panelPestanas = new JTabbedPane(); getContentPane().add(panelPestanas); { panel1 = new JPanel(); panelPestanas.addTab(“Pestaña 1”, panel1); } { panel2 = new JPanel(); panelPestanas.addTab(“Pestaña 2”, new ImageIcon(“img/informacion.png”), panel2); } } setSize(400, 300); } } El resultado es como se muestra en la Figura 24. 170 PR R O EP H I R BI O D D O U C IR Interfaz gráfica de usuario (GUI) Figura 24. JTabbedPane 11.3 Componentes Existen diferentes componentes que pueden ser utilizados en una aplicación para presentar la información y proveer servicios a la aplicación. Idealmente, los componentes deben agregarse dentro de un panel ϐ componentes, de acuerdo a sus características o servicios. ϐÀ Ǥ propiedades pueden estar dadas por el tamaño, color y posición, entre otros. Así mismo, el método getContentPane permite agregar un componente a un JFrame. El método setBound permite colocarle posición y tamaño al componente con respecto al JFrame, donde los ϐ ×ǡ ïϐÓ en píxeles. 171 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández 11.3.1 -%XWWRQ Un JButton es un botón, el cual provee un servicio fundamental de invocar un método, cuando el usuario hace clic sobre dicho botón. Un ×ǡǡϐ ±Ǥ sintaxis para crear un botón es la siguiente: PR R O EP H I R BI O D D O U C IR JButton boton = new JButton(“Mi botón”); Si se desea cambiar el texto se usa el método setText de la siguiente forma: boton.setText(“Nuevo texto”); 11.3.2 JTextField Un JTextField es un cuadro de texto que provee un servicio fundamental como es permitir al usuario introducir o visualizar texto. La sintaxis para crear un cuadro de texto es la siguiente: JTextFieldcuadroTexto = new JTextField(“Texto”); Si se desea cambiar el texto se usa el método setText de la siguiente forma: cuadroTexto.setText(“Nuevo texto”); 11.3.3 JLabel Un JLabel es una etiqueta, la cual provee únicamente la opción de visualizar información. La sintaxis para crear una etiqueta es la siguiente: JLabel etiqueta = new JLabel(“Texto”); Si se desea cambiar el texto se usa el método setText de la siguiente forma: etiqueta.setText(“Nuevo texto”); 172 Interfaz gráfica de usuario (GUI) 11.3.4 -5DGLR%XWWRQ Un JRadioButton es un componente que permite realizar una sola selección entre un conjunto de opciones. La sintaxis para crear un radio botón es la siguiente: JRadioButton radioBoton = new JRadioButton(“Texto de opcion”); PR R O EP H I R BI O D D O U C IR Para poder realizar la activación correcta del radio botón, en donde solo debe haber un botón activo a la vez, se debe hacer una agrupación mediante un ButtonGroup. Para agrupar tres radio botones, la sintaxis es la siguiente: JRadioButton radioBoton1 = new JRadioButton(“Opcion 1”); JRadioButton radioBoton2 = new JRadioButton(“Opcion 2”); JRadioButton radioBoton3 = new JRadioButton(“Opcion 3”); ButtonGroup grupoRadioBoton = new ButtonGroup(); grupoRadioBoton.add(radioBoton1); grupoRadioBoton.add(radioBoton2); grupoRadioBoton.add(radioBoton3); El JRadioButton posee dos métodos para la manipulación de la selección del componente que son: x isSelected(). Retorna verdadero si el JRadioButton se encuentra seleccionado y falso si no se encuentra seleccionado. x setSelected(boolean b). Selecciona el JRadioButton si el parámetro es verdadero. Al usar este método se retira de forma automática la selección de los demás JRadioButton que hagan parte del ButtonGroup. 11.3.5 JCheckBox Un JCheckBox es un componente que permite realizar múltiples selecciones de opciones. La sintaxis para crear un checkbox es la siguiente: 173 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández JCheckBox checkBox = new JCheckBox(“Texto de opcion”); El JCheckBox posee dos métodos para la manipulación de la selección del componente que son: x isSelected(). Retorna verdadero si el JCheckBox se encuentra seleccionado y falso si no se encuentra seleccionado. PR R O EP H I R BI O D D O U C IR x setSelected(boolean b). Selecciona el JCheckBox si el parámetro es verdadero. 11.3.6 JTextArea Un JTextArea es un área de texto que permite tener múltiples líneas de texto. La sintaxis para crear un área de texto es la siguiente: JTextAreaareaTexto = new JTextArea(); Si se desea asignar el número de líneas de texto para el área de texto, se debe hacer uso del método setRows, el cual recibe un parámetro ïϐ texto. areaTexto.setRows(10); 11.3.7 JList Un JList es una lista, la cual permite visualizar un conjunto de textos. Estos textos pueden ser seleccionados en tiempo de ejecución de forma simple o múltiple, es decir, el usuario puede seleccionar uno o varios textos. La sintaxis para crear una lista es la siguiente: JListlista = new JList(); 174 Interfaz gráfica de usuario (GUI) Para agregar información en una lista, se pueden utilizar varias técnicas. Las técnicas más utilizadas son las siguientes: x Crear un arreglo de String y enviarlo al JList como parámetro en el constructor. La implementación de esta solución es la siguiente. PR R O EP H I R BI O D D O U C IR String[] textos = {“Texto 1”,”Texto 2”,”Texto 3”,”..”,”Texto n”}; JList lista = new JList(textos); x Crear un DefaultListModel, y a través del método addElement, agregar los textos que se requieran adicionar a la lista. El DefaultListModel se asigna a la lista a través del método setModel de la clase JList. La implementación de esta solución es la siguiente: JList lista = new JList(); DefaultListModel modeloLista = new modeloLista.addElement(“Texto 1”); modeloLista.addElement(“Texto 2”); modeloLista.addElement(“Texto 3”); modeloLista.addElement(“..”); modeloLista.addElement(“Texto n”); lista.setModel(modeloLista); DefaultListModel(); x Usar la interfaz ListModel y la clase DefaultComboBoxModel, creando un objeto referencia de ListModel e instancia de DefaultComboBoxModel, asignando en su constructor un arreglo de String con los textos requeridos. El ListModel se asigna a la lista a través del método setModel de la clase JList. La implementación de esta solución es la siguiente: ListModel modeloLista = new DefaultComboBoxModel(new String[] {“Texto 1”,”Texto 2”,”Texto 3”,”..”,”Texto n”}); JList lista = new JList(); lista.setModel(modeloLista); La implementación de una aplicación de las tres soluciones anteriores es la siguiente: 175 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández SDFNDJHLQWHUID]*UD¿FDOLVW import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListModel; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.ListModel; import javax.swing.WindowConstants; PR R O EP H I R BI O D D O U C IR public class FPrincipal extends JFrame { private JList lista1; private JList lista2; private JList lista3; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); } 176 private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(null); { String[] textos = {“Lista 1”, “Texto 1”, “Texto 2”, “Texto 3”, “..”, “Texto n”}; lista1 = new JList(textos); getContentPane().add(lista1); lista1.setBounds(40, 30, 80, 150); } { lista2 = new JList(); DefaultListModel modeloLista = new DefaultListModel(); modeloLista.addElement(“Lista 2”); modeloLista.addElement(“Texto 1”); modeloLista.addElement(“Texto 2”); modeloLista.addElement(“Texto 3”); modeloLista.addElement(“..”); modeloLista.addElement(“Texto n”); lista2.setModel(modeloLista); getContentPane().add(lista2); lista2.setBounds(160, 30, 80, 150); } { Interfaz gráfica de usuario (GUI) ListModel modeloLista = new DefaultComboBoxModel( new String[] {“Lista 3”, “Texto 1”, “Texto 2”, “Texto 3”, “..”, “Texto n”}); lista3 = new JList(); lista3.setModel(modeloLista); getContentPane().add(lista3); lista3.setBounds(280, 30, 80, 150); } setSize(400, 300); } PR R O EP H I R BI O D D O U C IR } ʹͷǤ Figura 25. JList El JList posee cuatro métodos para la manipulación de la selección del componente que son: x getSelectedIndex(). seleccionado. Retorna el índice del elemento x getSelectedIndices(). Retorna un arreglo de enteros con los índices de los elementos seleccionados. x getSelectedValue(). Retorna un objeto con el valor del elemento seleccionado. 177 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández x getSelectedValues(). Retorna un arreglo de objetos con los valores de los elementos seleccionados. 11.3.8 JComboBox PR R O EP H I R BI O D D O U C IR Un JComboBox es un componente que combina un cuadro de texto con una lista. Se usa con frecuencia en situaciones donde se requiere seleccionar y visualizar solo un resultado de la lista. La sintaxis para crear un combo es la siguiente: JComboBox combo = new JComboBox(); Para agregar información en un combo se pueden utilizar varias técnicas. La técnica más utilizadas consisten en usar la interfaz ComboBoxModel y la clase DefaultComboBoxModel, creando un objeto referencia de ComboBoxModel e instancia de DefaultComboBoxModel, asignando en su constructor un arreglo de String con los textos requeridos. El ComboBoxModel se asigna al combo a través del método setModel de la clase JComboBox. La implementación de esta solución es la siguiente: SDFNDJHLQWHUID]*UD¿FDFRPER%R[ import javax.swing.ComboBoxModel; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private JComboBox combo; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); } 178 Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(null); { ComboBoxModel comboModel = new DefaultComboBoxModel( new String[] {“Seleccione”, “Texto 1”, “Texto 2”, “Texto 3”, “..”, “Texto n”}); combo = new JComboBox(); getContentPane().add(combo); combo.setModel(comboModel); combo.setBounds(120, 50, 110, 20); } setSize(400, 300); } } El resultado es como se presenta en la Figura 26. Figura 26. JComboBox El JList posee dos métodos para la manipulación de la selección del componente que son: 1. getSelectedIndex(). seleccionado. Retorna el índice del elemento 179 Héctor Arturo Flórez Fernández Programación Orientada a Objetos usando Java 2. getSelectedItem(). seleccionado. Retorna el objeto del elemento 11.3.9 JTable PR R O EP H I R BI O D D O U C IR Un JTable es un componente que permite visualizar información en Ǥ ϐ Ǥ un JTable ϐǡ ϐ columna seleccionada y muchas otras funciones. La sintaxis para crear una tabla es la siguiente: JTable tabla = new JTable(); Para asignar información a una tabla es necesario hacer uso de la interfaz TableModel y la clase DefaultTableModel, creando un objeto referencia de TableModel e instancia de DefaultTableModel, asignando en su constructor una matriz tipo String que contenga los datos y un arreglo tipo String con los títulos. Este modelo se debe asignar a la tabla mediante el método setModel. La sintaxis para asignar un TableModel a un JTable es la siguiente: String [][] datos = {{“Dato Fila 0 Columna 0”,”Dato Fila 0 Columna 1”,”Dato Fila 0 Columna 2”}, {“Dato Fila 1 Columna 0”,”Dato Fila 1 Columna 1”,”Dato Fila 1 Columna 2”}}; String [] titulos = new String[] { “Columna 0”, “Columna 2”, “Columna 3”}; TableModel modeloTabla = new DefaultTableModel(datos, titulos); tabla.setModel(modeloTabla); La manera más usual de utilizar una tabla es a través del contenedor JScrollPane, el cual permite que se activen de forma automática las barras de desplazamiento para visualizar toda la información de la tabla, en el caso que la información no pueda ser visualizada por el tamaño de la tabla. Para asignar una tabla a un JScrollPane, se hace uso del método setViewportView. Al utilizar un JScrollPane es necesario asignar el tamaño interno de la tabla mediante el método 180 Interfaz gráfica de usuario (GUI) setPreferredSize, el cual recibe como parámetro un objeto instancia de la clase Dimensión que recibe como parámetros, el ancho y alto de la tabla. La sintaxis para asignar un JTable a un JScrollPane es la siguiente: PR R O EP H I R BI O D D O U C IR JScrollPane scrollPane = new JScrollPane(); scrollPane.setViewportView(tabla); tabla.setPreferredSize(new Dimension(350,datos.length*16)); En el ejemplo anterior, el parámetro datos.length*16, permite ϐ ï ϐ ͳÀϐ en el tipo y tamaño de fuente por defecto. ǡ ϐ la clase TableRowSorter. Es necesario crear una instancia de TableRowSorter enviando como parámetro al constructor el modelo de la tabla. Posteriormente, se le asigna a la tabla mediante el método setRowSorter. La sintaxis para asignar un TableRowSorter a un JTable es la siguiente: TableRowSorter ordenador=new TableRowSorter(modeloTabla); tabla.setRowSorter(ordenador); Un ejemplo de implementación de una tabla en un frame, con todas las características presentadas es el siguiente: SDFNDJHLQWHUID]*UD¿FDWDEOH import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.WindowConstants; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; 181 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández public class FPrincipal extends JFrame { private JTable tabla; private JScrollPane scrollPane; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } PR R O EP H I R BI O D D O U C IR public FPrincipal() { initGUI(); } } 182 private void initGUI() { VHW'HIDXOW&ORVH2SHUDWLRQ :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(null); { scrollPane = new JScrollPane(); getContentPane().add(scrollPane); scrollPane.setBounds(40, 20, 320, 120); { String [][] datos = {{“10”,”Hector”, ”Florez”,”123”}, {“20”,”Arturo”,”Fernandez”,”456”}, {“30”,”Juan”,”Valdez”,”789”}, {“40”,”Pepito”, ”Perez”,”987”},{“50”,”Pedro”,”Picapiedra”,”123”}, {“60”,”Pablo”,”Marmol”,”456”}, {“70”,”Homero”, ”Simpson”,”789”}, {“80”,”Bart”,”Simpson”,”987”}}; 6WULQJ>@WLWXORV QHZ6WULQJ>@^³,GHQWL¿FDFLRQ´ “Nombre”, “Apellido”, “Telefono”}; TableModel modeloTabla = new DefaultTableModel(datos, titulos); tabla = new JTable(); tabla.setModel(modeloTabla); tabla.setPreferredSize(new Dimension(350,datos.length*16)); scrollPane.setViewportView(tabla); TableRowSorter ordenador = new TableRowSorter(modeloTabla); tabla.setRowSorter(ordenador); } } setSize(400, 300); } Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR El resultado es como se presenta en la Figura 27. Figura 27. JTable Al agregar más información en la tabla se activan de forma automática, las barras de desplazamiento necesarias como se muestra en la ʹͺǤ Figura 28. JTable con JScrollPane 183 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Al hacer clic sobre el título de la columna “Nombre” se realiza el ordenamiento automático de los datos de la tabla, como se muestra en la Figura 29. Figura 29. JTable ordenado 11.4 Cuadros de diálogo 11.4.1 -2SWLRQ3DQH La clase JOptionPane contiene una gran cantidad de atributos y métodos estáticos que permiten generar diferentes tipos de cuadros de diálogo. Reciben diferentes parámetros de acuerdo al tipo de cuadro de mensaje, sin embargo, todos los cuadros de mensaje reciben, en su primer parámetro, un componente que hace referencia al JFrame Ǥ ǡ cuadro de diálogo depende del JFrame que hace uso de dicho cuadro, por tal razón, el primer parámetro puede contener la sentencia this. ϐ ǣ x Cuadros de diálogo de mensaje. Un cuadro de mensaje presenta una información al usuario como resultado de una 184 Interfaz gráfica de usuario (GUI) operación. Este mensaje está acompañado de un ícono que permite indicar, si el mensaje es de información, error o advertencia. PR R O EP H I R BI O D D O U C IR x ϐ ×Ǥ Un cuadro de ϐ ×SI, NO y CANCELAR. Cada uno de estos botones poseen un valor que puede ser capturado en la aplicación. x Cuadros de diálogo de entrada de información. Un cuadro de entrada provee un cuadro de texto para que el usuario digite allí una información, que va a ser capturada en una cadena de caracteres en la aplicación. x Cuadros de diálogo de opciones. Un cuadro de opciones provee un conjunto de botones que se envían a través de un arreglo. Este cuadro puede tener un ícono personalizado, mensaje y título. El cuadro retorna el índice de la opción seleccionado por el usuario a través de un clic sobre un botón. Cuadro de mensaje de información JOptionPane.showMessageDialog(this, “Mensaje de informacion del FXDGURGHGLDORJR´³7LWXOR´-2SWLRQ3DQH,1)250$7,21B0(66$*( Figura 30. JOptionPane. Cuadro de mensaje de información 185 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Cuadro de mensaje de error PR R O EP H I R BI O D D O U C IR JOptionPane.showMessageDialog(this, “Mensaje de error del cuadro GHGLDORJR´³7LWXOR´-2SWLRQ3DQH(5525B0(66$*( Figura 31. JOptionPane. Cuadro de mensaje de error Cuadro de mensaje de advertencia JOptionPane.showMessageDialog(this, “Mensaje de advertencia del FXDGURGHGLDORJR´³7LWXOR´-2SWLRQ3DQH:$51,1*B0(66$*( Figura 32. JOptionPane. Cuadro de mensaje de advertencia ϔ × LQWDFFLRQ -2SWLRQ3DQHVKRZ&RQ¿UP'LDORJ WKLV³0HQVDMHGH FRQ¿UPDFLRQ´ LI DFFLRQ -2SWLRQ3DQH<(6B237,21 ^ //Entra si hace clic en SI `HOVHLI DFFLRQ -2SWLRQ3DQH12B237,21 ^ //Entra si hace clic en NO 186 Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR `HOVHLI DFFLRQ -2SWLRQ3DQH&$1&(/B237,21 ^ //Entra si hace clic en CANCELAR } Figura 33. JOptionPaneǤ Ƥ × Cuadro de mensaje de entrada de información String informacion = JOptionPane.showInputDialog(this, “Mensaje de solicitud de informacion”); Figura 34. JOptionPane. Cuadro de mensaje de entrada de información Cuadro de mensaje de opción con botones String []opciones={“Opcion 1”,”Opcion 2”,”Opcion 3”,”Opcion n”}; ImageIcon imagen = new ImageIcon(“img/opcion.png”); int indice = JOptionPane.showOptionDialog(this, “Mensaje de seleccion de opciones”, “Titulo”, 1, 1, imagen, opciones, “1”); 187 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 35. JOptionPane. Cuadro de mensaje de opción con botones Cuadro de mensaje de opción con comboBox String []opciones={“Opcion 1”,”Opcion 2”,”Opcion 3”,”Opcion n”}; JOptionPane.showInputDialog(this, “Mensaje de seleccion de RSFLRQHV´³7LWXOR´-2SWLRQ3DQH3/$,1B0(66$*(QXOORSFLRQHV “?”); Figura 36. JOptionPane. Cuadro de mensaje de opción con comboBox 188 Interfaz gráfica de usuario (GUI) 11.4.2 JFileChooser PR R O EP H I R BI O D D O U C IR El JFileChooser permite abrir diferentes tipos de cuadros de diálogo, para abrir archivos de cualquier tipo. Esta clase tiene atributos y métodos para abrir cuadros de diálogo, para guardar y abrir archivos. Los métodos showSaveDialog y showOpenDialog reciben por parámetro un contenedor. Este contenedor puede ser el JFrame que contiene la aplicación o un JPanel. Si se desea incluir el JFrame y el código para abrir el JFileChooser está en dicho JFrame, se debe enviar por parámetro la sentencia this, la cual hace referencia a dicho JFrame. Al colocar un contenedor, el cuadro de diálogo aparece en el centro de dicho contenedor. Cuadro de diálogo de guardar JFileChooser ventana = new JFileChooser(); int seleccion = ventana.showSaveDialog(this); LI VHOHFFLRQ -)LOH&KRRVHU$33529(B237,21 ^ )LOH¿OH YHQWDQDJHW6HOHFWHG)LOH `HOVHLI VHOHFFLRQ -)LOH&KRRVHU&$1&(/B237,21 ^ //TODO Código de cancelar } Figura 37. JFileChooser. Cuadro de diálogo para guardar archivo 189 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Cuadro de diálogo de abrir PR R O EP H I R BI O D D O U C IR JFileChooser ventana = new JFileChooser(); int seleccion = ventana.showOpenDialog(this); LI VHOHFFLRQ -)LOH&KRRVHU$33529(B237,21 ^ )LOH¿OH YHQWDQDJHW6HOHFWHG)LOH `HOVHLI VHOHFFLRQ -)LOH&KRRVHU&$1&(/B237,21 ^ //TODO Código de cancelar } Figura 38. JFileChooser. Cuadro de diálogo para abrir archivo Àϐ con colocar, en el constructor del JFileChooser, la ruta deseada. La implementación es la siguiente: JFileChooser ventana = new JFileChooser(“./img”); int seleccion = ventana.showOpenDialog(null); LI VHOHFFLRQ -)LOH&KRRVHU$33529(B237,21 ^ )LOH¿OH YHQWDQDJHW6HOHFWHG)LOH `HOVHLI VHOHFFLRQ -)LOH&KRRVHU&$1&(/B237,21 ^ //TODO Código de cancelar } 190 PR R O EP H I R BI O D D O U C IR Interfaz gráfica de usuario (GUI) Figura 39. JFileChooser. Cuadro de diálogo para abrir archivo con ruta relativa El JFileChooser ×ϐ Ǥ casos anteriores, en el cuadro que hace referencia al tipo de archivo, solo existe la opción “Todos los archivos”. A través de la clase abstracta FileFilter ϐϐ ϐǡ tal manera que al seleccionar uno de ellos se presenta en el cuadro de exploración solamente las carpetas y archivos que contengan la ×ϐ Ǥ ϐ que extienda de FileFilter. Este procedimiento obliga a implementar los métodos abstractos accept y getDescription. La implementación es la siguiente: SDFNDJHLQWHUID]*UD¿FD¿OH&KRRVHU import java.io.File; LPSRUWMDYD[VZLQJ¿OHFKRRVHU)LOH)LOWHU public class Filtro extends FileFilter{ 191 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández private String ext; private String description; public Filtro(){ this.ext = “.haff”; this.description = “Archivos Hector Florez (*.haff)”; } PR R O EP H I R BI O D D O U C IR @Override public String getDescription() { return this.description; } @Override public boolean accept(File f) { return f.getName().toLowerCase().endsWith ( this.ext)||f.isDirectory(); } } El método accept recibe como parámetro un File que hace referencia al archivo seleccionado, en caso que se acepte y corresponda con la × ϐǤ ǡ no se cierra. ϐJFileChooser es necesario utilizar el método addChoosableFileFilter del JFileChooser, enviándole como parámetro ϐǤǣ )LOWUR¿OWUR QHZ)LOWUR YHQWDQDDGG&KRRVDEOH)LOH)LOWHU ¿OWUR × ϐ siguiente: JFileChooser ventana = new JFileChooser(); )LOWUR¿OWUR QHZ)LOWUR YHQWDQDDGG&KRRVDEOH)LOH)LOWHU ¿OWUR int seleccion = ventana.showOpenDialog(null); LI VHOHFFLRQ -)LOH&KRRVHU$33529(B237,21 ^ )LOH¿OH YHQWDQDJHW6HOHFWHG)LOH `HOVHLI VHOHFFLRQ -)LOH&KRRVHU&$1&(/B237,21 ^ //TODO Código de cancelar } 192 Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR El resultado de la asignación del filtro es como se muestra en la ͶͲǤ Figura 40. JFileChooser utilizando FileFilter ͶͲ ǡ ϐ ϐ × Ǥ ï ϐ FileFilterǤ ϐ ϐ ǡ × ×ϐ Ǥ ǡÀϐ Ǥ × es la siguiente: SDFNDJHLQWHUID]*UD¿FD¿OH&KRRVHU import java.io.File; LPSRUWMDYD[VZLQJ¿OHFKRRVHU)LOH)LOWHU 193 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández public class Filtro extends FileFilter{ private String ext; private String description; public Filtro(String ext, String description){ this.ext = ext; this.description = description; } PR R O EP H I R BI O D D O U C IR @Override public String getDescription() { return this.description; } @Override public boolean accept(File f) { return f.getName().toLowerCase().endsWith ( this.ext)||f.isDirectory(); } } ϐ ϐǤ Al instanciar cada objeto del arreglo se envían como parámetros la extensión y la descripción. La sintaxis es la siguiente: )LOWUR>@¿OWUR QHZ)LOWUR>@ ¿OWUR>@ QHZ)LOWUR ³GRF[´´$UFKLYRVGHZRUG GRF[ ´ ¿OWUR>@ QHZ)LOWUR ³[OV[´´$UFKLYRVGHH[FHO [OV[ ´ ¿OWUR>@ QHZ)LOWUR ³SSW[´´$UFKLYRVGHSRZHUSRLQW (*.pptx)”); ¿OWUR>@ QHZ)LOWUR ³SGI´´$UFKLYRVSGI SGI ´ ¿OWUR>@ QHZ)LOWUR ³W[W´´$UFKLYRVEORFNGHQRWDV W[W ´ for(int i=0; i<5; i++){ YHQWDQDDGG&KRRVDEOH)LOH)LOWHU ¿OWUR>L@ } La implementación para abrir un cuadro de diálogo con múltiples ϐǣ JFileChooser ventana = new JFileChooser(); )LOWUR>@¿OWUR QHZ)LOWUR>@ ¿OWUR>@ QHZ)LOWUR ³GRF[´´$UFKLYRVGHZRUG GRF[ ´ ¿OWUR>@ QHZ)LOWUR ³[OV[´´$UFKLYRVGHH[FHO [OV[ ´ ¿OWUR>@ QHZ)LOWUR ³SSW[´´$UFKLYRVGHSRZHUSRLQW (*.pptx)”); ¿OWUR>@ QHZ)LOWUR ³SGI´´$UFKLYRVSGI SGI ´ ¿OWUR>@ QHZ)LOWUR ³W[W´´$UFKLYRVEORFNGHQRWDV W[W ´ for(int i=0; i<5; i++){ 194 Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR YHQWDQDDGG&KRRVDEOH)LOH)LOWHU ¿OWUR>L@ } int seleccion = ventana.showOpenDialog(null); LI VHOHFFLRQ -)LOH&KRRVHU$33529(B237,21 ^ )LOH¿OH YHQWDQDJHW6HOHFWHG)LOH `HOVHLI VHOHFFLRQ -)LOH&KRRVHU&$1&(/B237,21 ^ //TODO Código de cancelar } Figura 41. JFileChooser utilizando múltiples FileFilter 11.5 Layout Un layout es un objeto que permite controlar la posición y tamaño de un conjunto de componentes en un contenedor. 11.5.1 AbsoluteLayout La clase AbsolutLayout permite organizar elementos de forma estática en un contenedor. El elemento que se agrega al contenedor debe 195 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández establecer la posición y tamaño a través de los siguientes métodos: x setBounds que permite asignar posición a través de coordenadas X, Y y tamaño, a través de atributos que indican el ancho y alto. PR R O EP H I R BI O D D O U C IR x setSize que permite asignar tamaño a través de atributos que indican el ancho y alto. x setPosition que permite asignar posición a través de coordenadas las X, Y. La sintaxis para asignar un AbsoluteLayout a un contenedor, como por ejemplo un panel, es la siguiente: JPanel panel = new JPanel(); panel.setLayout(null); La siguiente implementación permite establecer un JFrame con AbsoluteLayout en el cual se adicionan seis botones con diferentes posiciones y tamaños. SDFNDJHLQWHUID]*UD¿FDOD\RXWDEVROXW/D\RXW import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private JButton boton1; private JButton boton2; private JButton boton3; private JButton boton4; private JButton boton5; private JButton boton6; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); } 196 Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(null); { boton1 = new JButton(); getContentPane().add(boton1); boton1.setText(“boton 1”); boton1.setBounds(30, 5, 101, 21); } { boton2 = new JButton(); getContentPane().add(boton2); boton2.setText(“boton 2”); boton2.setBounds(35, 90, 97, 21); } { boton3 = new JButton(); getContentPane().add(boton3); boton3.setText(“boton 3”); boton3.setBounds(142, 52, 110, 38); } { boton4 = new JButton(); getContentPane().add(boton4); boton4.setText(“boton 4”); boton4.setBounds(65, 167, 123, 62); } { boton5 = new JButton(); getContentPane().add(boton5); boton5.setText(“boton 5”); boton5.setBounds(218, 119, 117, 46); } { boton6 = new JButton(); getContentPane().add(boton6); boton6.setText(“boton 6”); boton6.setBounds(278, 73, 93, 35); } setSize(400, 300); } } Al ejecutar la implementación anterior se presenta el resultado de la Figura 42. 197 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 42. Absolute Layout 11.5.2 BorderLayout La clase BorderLayout permite organizar elementos dinámicamente en un contenedor, con base en cinco posiciones. Entonces, solo se puede visualizar máximo cinco elementos en un contenedor con BorderLayout. Las posiciones son las siguientes: 1. CENTER. Esta posición permite colocar el elemento en el centro del contendor. 2. NORTH. Esta posición permite colocar el elemento en la parte superior del contendor. 3. SOUTH. Esta posición permite colocar el elemento en la parte inferior del contendor. 4. WEST. Esta posición permite colocar el elemento en la parte izquierda del contendor. 5. EAST. Esta posición permite colocar el elemento en la parte derecha del contendor. 198 Interfaz gráfica de usuario (GUI) Si un único elemento está en el contenedor con BorderLayout, independientemente de su posición, el elemento ocupará todo el contenedor. La sintaxis para asignar un BorderLayout a un contenedor, como por ejemplo un panel, es la siguiente: PR R O EP H I R BI O D D O U C IR JPanel panel = new JPanel(); BorderLayout layout = new BorderLayout(); panel.setLayout(layout); La sintaxis para agregar un elemento, como por ejemplo, un botón a un panel con BorderLayout en la posición center, es la siguiente: JButton boton = new JButton(“Boton”); panel.add(Boton1, BorderLayout.CENTER); La siguiente implementación permite establecer un JFrame con BorderLayout en el cual se adicionan cinco botones en todas las posiciones posibles. SDFNDJHLQWHUID]*UD¿FDOD\RXWERUGHU/D\RXW import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private JButton boton1; private JButton boton2; private JButton boton3; private JButton boton4; private JButton boton5; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } 199 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández public FPrincipal() { initGUI(); } PR R O EP H I R BI O D D O U C IR private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); BorderLayout thisLayout = new BorderLayout(); getContentPane().setLayout(thisLayout); { boton1 = new JButton(); getContentPane().add(boton1, BorderLayout.CENTER); boton1.setText(“Boton 1”); } { boton2 = new JButton(); getContentPane().add(boton2, BorderLayout.NORTH); boton2.setText(“Boton 2”); } { boton3 = new JButton(); getContentPane().add(boton3, BorderLayout.WEST); boton3.setText(“Boton 3”); } { boton4 = new JButton(); getContentPane().add(boton4, BorderLayout.EAST); boton4.setText(“Boton 4”); } { boton5 = new JButton(); getContentPane().add(boton5, BorderLayout.SOUTH); boton5.setText(“Boton 5”); } pack(); setSize(400, 300); } } Al ejecutar la implementación anterior se presenta el resultado de la Ͷ͵Ǥ 200 PR R O EP H I R BI O D D O U C IR Interfaz gráfica de usuario (GUI) Figura 43. Border Layout 11.5.3 FlowLayout La clase FlowLayout permite organizar elementos dinámicamente en un contenedor, en donde la posición de los elementos depende del orden en que son agregados al contenedor. Estos elementos están colocados uno seguido del otro. La sintaxis para asignar un FlowLayout a un contenedor, como por ejemplo un panel, es la siguiente: JPanel panel = new JPanel(); FlowLayout layout = new FlowLayout(); panel.setLayout(layout); La siguiente implementación permite establecer un JFrame con FlowLayout en el cual se adicionan cinco botones. pDFNDJHLQWHUID]*UD¿FDOD\RXWÀRZ/D\RXW import java.awt.FlowLayout; import javax.swing.JButton; 201 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private JButton boton1; private JButton boton2; private JButton boton3; private JButton boton4; private JButton boton5; PR R O EP H I R BI O D D O U C IR public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); } } 202 private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( this.setTitle(“Frame Principal”); FlowLayout thisLayout = new FlowLayout(); getContentPane().setLayout(thisLayout); { boton1 = new JButton(); getContentPane().add(boton1); boton1.setText(“Boton 1”); } { boton2 = new JButton(); getContentPane().add(boton2); boton2.setText(“Boton 2”); } { boton3 = new JButton(); getContentPane().add(boton3); boton3.setText(“Boton 3”); } { boton4 = new JButton(); getContentPane().add(boton4); boton4.setText(“Boton 4”); } { boton5 = new JButton(); getContentPane().add(boton5); boton5.setText(“Boton 5”); } setSize(400, 300); } Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR Al ejecutar la implementación anterior se presenta el resultado de la Figura 44. Figura 44. Flow Layout 11.5.4 GridLayout La clase GridLayout permite organizar elementos dinámicamente en un contenedor, en donde la posición de los elementos depende del orden en que son agregados al contenedor. Estos elementos están ǡ ϐ ϐ en el GridLayout. Además, se puede establecer una separación de los componentes agregados en el contenedor. La sintaxis para asignar un GridLayout a un contenedor, como por ejemplo un panel, es la siguiente: JPanel panel = new JPanel(); GridLayout layout = new GridLayout(3, 2, 10, 10); panel.setLayout(layout); En el ejemplo anterior, el constructor del GridLayout recibe cuatro ǤǡïϐǢǡ 203 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández número de columnas; el tercero, la separación de los componentes en el eje X medido en píxeles y el cuarto, la separación de los componentes en el eje Y medido en píxeles. La siguiente implementación permite establecer un JFrame con GridLayout, en el cual se adicionan seis botones. SDFNDJHLQWHUID]*UD¿FDOD\RXWJULG/D\RXW PR R O EP H I R BI O D D O U C IR import java.awt.GridLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private JButton boton1; private JButton boton2; private JButton boton3; private JButton boton4; private JButton boton5; private JButton boton6; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); } 204 private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); GridLayout thisLayout = new GridLayout(3, 2, 10, 10); getContentPane().setLayout(thisLayout); { boton1 = new JButton(); getContentPane().add(boton1); boton1.setText(“Boton 1”); } { boton2 = new JButton(); getContentPane().add(boton2); boton2.setText(“Boton 2”); } Interfaz gráfica de usuario (GUI) { boton3 = new JButton(); getContentPane().add(boton3); boton3.setText(“Boton 3”); } { boton4 = new JButton(); getContentPane().add(boton4); boton4.setText(“Boton 4”); } { PR R O EP H I R BI O D D O U C IR boton5 = new JButton(); getContentPane().add(boton5); boton5.setText(“Boton 5”); } { boton6 = new JButton(); getContentPane().add(boton6); boton6.setText(“Boton 6”); } setSize(400, 300); } } Al ejecutar la implementación anterior, se presenta el resultado de la ͶͷǤ Figura 45. Grid Layout 205 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández 11.6 Formularios Con base en contenedores, componentes y layouts, se pueden diseñar diferentes tipos de formularios para realizar operaciones típicas de manipulación de datos en sistemas de información. PR R O EP H I R BI O D D O U C IR Por ejemplo, un formulario completo para almacenar información de clientes en un sistema podría contener los siguientes elementos: x Datos Básicos o ϐ × o Nombre o Apellido o ± x Datos de Contacto o Correo o Teléfono o Celular x Datos de Ubicación o Dirección o País o Departamento o Ciudad x Pasatiempos o Deportes o Hobbies Con la información anterior se puede hacer un diseño basado en el panel de pestañas, para poder presentar de forma clara todos los elementos para la visualización. Debido a la gran cantidad de elementos es apropiado crear los paneles de cada pestaña por separado. La primera pestaña contendrá los datos básicos. Este panel contiene un GridLayout ϐ Ǥ± 206 Interfaz gráfica de usuario (GUI) como RadioButton, el cual debe estar dentro de un panel que tiene FlowLayout. La implementación del panel correspondiente es la siguiente: Clase PDatosBasicos SDFNDJHLQWHUID]*UD¿FDIRUPXODULR PR R O EP H I R BI O D D O U C IR import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridLayout; import javax.swing.ButtonGroup; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTextField; public class PDatosBasicos extends JPanel { SULYDWH-/DEHOODEHO,GHQWL¿FDFLRQ SULYDWH-7H[W)LHOGWH[W,GHQWL¿FDFLRQ private JLabel labelNombre; private JTextField textNombre; private JLabel labelApellido; private JTextField textApellido; private JLabel labelGenero; private JPanel panelGenero; private ButtonGroup buttonGroupGenero; private JRadioButton radioFemenino; private JRadioButton radioMasculio; public PDatosBasicos() { initGUI(); } private void initGUI() { setLayout(new GridLayout(4, 2, 5, 5)); { ODEHO,GHQWL¿FDFLRQ QHZ-/DEHO WKLVDGG ODEHO,GHQWL¿FDFLRQ ODEHO,GHQWL¿FDFLRQVHW7H[W ³,GHQWL¿FDFLRQ´ } { WH[W,GHQWL¿FDFLRQ QHZ-7H[W)LHOG WKLVDGG WH[W,GHQWL¿FDFLRQ 207 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández } { labelNombre = new JLabel(); this.add(labelNombre); labelNombre.setText(“Nombre”); } { textNombre = new JTextField(); this.add(textNombre); PR R O EP H I R BI O D D O U C IR } { labelApellido = new JLabel(); this.add(labelApellido); labelApellido.setText(“Apellido”); } { textApellido = new JTextField(); this.add(textApellido); } { labelGenero = new JLabel(); this.add(labelGenero); labelGenero.setText(“Genero”); } { panelGenero = new JPanel(); FlowLayout panelGeneroLayout = new FlowLayout(); this.add(panelGenero); panelGenero.setLayout(panelGeneroLayout); buttonGroupGenero = new ButtonGroup(); { radioFemenino = new JRadioButton(); panelGenero.add(radioFemenino); radioFemenino.setText(“Femenino”); buttonGroupGenero.add(radioFemenino); } { radioMasculio = new JRadioButton(); panelGenero.add(radioMasculio); radioMasculio.setText(“Masculino”); buttonGroupGenero.add(radioMasculio); } } } } 208 Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR El resultado de este panel es el siguiente: Figura 46. Ejemplo de Formulario. Panel datos básicos La segunda pestaña contendrá los datos de contacto. Este panel contiene un GridLayoutϐ Ǥ × del panel correspondiente es la siguiente: Clase PDatosContacto SDFNDJHLQWHUID]*UD¿FDIRUPXODULR import java.awt.Dimension; import java.awt.GridLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; public class PDatosContacto extends JPanel { private JLabel labelCorreo; private JTextField textCorreo; private JLabel labelCelular; private JTextField textCelular; private JLabel labelTelefono; private JTextField textTelefono; public PDatosContacto() { initGUI(); } private void initGUI() { setLayout(new GridLayout(3, 2, 5, 5)); 209 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR setPreferredSize(new Dimension(400, 150)); { labelCorreo = new JLabel(); this.add(labelCorreo); labelCorreo.setText(“Correo”); } { textCorreo = new JTextField(); this.add(textCorreo); } { labelTelefono = new JLabel(); this.add(labelTelefono); labelTelefono.setText(“Telefono”); } { textTelefono = new JTextField(); this.add(textTelefono); } { labelCelular = new JLabel(); this.add(labelCelular); labelCelular.setText(“Celular”); } { textCelular = new JTextField(); this.add(textCelular); } } } El resultado de este panel es el siguiente: Figura 47. Ejemplo de Formulario. Panel datos de contacto La tercera pestaña contendrá los datos de ubicación. Este panel contiene un GridLayout ϐ Ǥ implementación del panel correspondiente es la siguiente: 210 Interfaz gráfica de usuario (GUI) Clase PDatosUbicacion SDFNDJHLQWHUID]*UD¿FDIRUPXODULR import java.awt.Dimension; import java.awt.GridLayout; import javax.swing.ComboBoxModel; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; PR R O EP H I R BI O D D O U C IR import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; public class PDatosUbicacion extends JPanel { private JLabel labelDireccion; private JTextField textDireccion; private JComboBox comboPais; private JLabel labelPais; private JLabel labelDepartamento; private JComboBox comboDepartamento; private JLabel labelCiudad; private JComboBox comboCiudad; public PDatosUbicacion() { initGUI(); } private void initGUI() { setLayout(new GridLayout(4, 2, 5, 5)); { labelDireccion = new JLabel(); this.add(labelDireccion); labelDireccion.setText(“Direccion”); } { textDireccion = new JTextField(); this.add(textDireccion); } { labelPais = new JLabel(); this.add(labelPais); labelPais.setText(“Pais”); } { ComboBoxModel comboPaisModel = new DefaultComboBoxModel( new String[] { “Pais 1”, “Pais 2”, “Pais 3” }); 211 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández comboPais = new JComboBox(); this.add(comboPais); comboPais.setModel(comboPaisModel); } { labelDepartamento = new JLabel(); this.add(labelDepartamento); labelDepartamento.setText(“Departamento”); } { PR R O EP H I R BI O D D O U C IR ComboBoxModel comboDepartamentoModel = new DefaultComboBoxModel( new String[] { “Departamento 1”, “Departamento 2” }); comboDepartamento = new JComboBox(); this.add(comboDepartamento); comboDepartamento.setModel(comboDepartamentoModel); } { labelCiudad = new JLabel(); this.add(labelCiudad); labelCiudad.setText(“Ciudad”); } { ComboBoxModel comboCiudadModel = new DefaultComboBoxModel( new String[] { “Ciudad 1”, “Ciudad 2” }); comboCiudad = new JComboBox(); this.add(comboCiudad); comboCiudad.setModel(comboCiudadModel); } } } El resultado de este panel es el siguiente: Figura 48. Ejemplo de Formulario. Panel datos de ubicación 212 Interfaz gráfica de usuario (GUI) La cuarta pestaña contendrá pasatiempos. Este panel contiene un FlowLayout. La implementación del panel correspondiente es la siguiente: Clase PPasatiempos paFNDJHLQWHUID]*UD¿FDIRUPXODULR PR R O EP H I R BI O D D O U C IR import java.awt.Dimension; import java.awt.FlowLayout; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JPanel; public class PPasatiempos extends JPanel { private JCheckBox checkFutbol; private JCheckBox checkBaloncesto; private JCheckBox checkNatacion; private JCheckBox checkCine; private JCheckBox checkTeatro; private JCheckBox checkAtletismo; private JCheckBox checkTenis; public PPasatiempos() { initGUI(); } private void initGUI() { this.setLayout(new FlowLayout()); setPreferredSize(new Dimension(400, 150)); { checkFutbol = new JCheckBox(); this.add(checkFutbol); checkFutbol.setText(“Futbol”); } { checkBaloncesto = new JCheckBox(); this.add(checkBaloncesto); checkBaloncesto.setText(“Baloncesto”); } { checkTenis = new JCheckBox(); this.add(checkTenis); checkTenis.setText(“Tenis”); } 213 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández { checkNatacion = new JCheckBox(); this.add(checkNatacion); checkNatacion.setText(“Natacion”); } { checkAtletismo = new JCheckBox(); this.add(checkAtletismo); checkAtletismo.setText(“Atletismo”); PR R O EP H I R BI O D D O U C IR } { checkTeatro = new JCheckBox(); this.add(checkTeatro); checkTeatro.setText(“Teatro”); } { checkCine = new JCheckBox(); this.add(checkCine); checkCine.setText(“Cine”); } } } El resultado de este panel es el siguiente: Figura 49. Ejemplo de Formulario. Panel pasatiempos Adicionalmente, un formulario debe tener botones que permitan ejecutar operaciones. Estas operaciones deben ser ejecutadas cuando el usuario lo decida. Entonces, se construye un panel que contenga botones. Este panel contiene un FlowLayout. La implementación del panel correspondiente es la siguiente: 214 Interfaz gráfica de usuario (GUI) PBotones paFNDJHLQWHUID]*UD¿FDIRUPXODULR import java.awt.Dimension; import java.awt.FlowLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; PR R O EP H I R BI O D D O U C IR public class PBotones extends JPanel { private JButton buttonAceptar; private JButton buttonCancelar; private JButton buttonLimpiar; public PBotones() { initGUI(); } private void initGUI() { setLayout(new FlowLayout()); setPreferredSize(new Dimension(400, 100)); { buttonAceptar = new JButton(); this.add(buttonAceptar); buttonAceptar.setText(“Aceptar”); } { buttonCancelar = new JButton(); this.add(buttonCancelar); buttonCancelar.setText(“Cancelar”); } { buttonLimpiar = new JButton(); this.add(buttonLimpiar); buttonLimpiar.setText(“Limpiar”); } } } El resultado de este panel es el siguiente: Figura 50. Ejemplo de Formulario. Panel botones 215 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Para incluir los paneles construidos se debe crear un JFrame que incluya un Label para colocar un título, un TabbedPane para incluir los demás paneles en pestañas y un panel de botones. Este frame contiene un BorderLayout. La implementación es la siguiente: Clase FFormulario PR R O EP H I R BI O D D O U C IR SDFNDJHLQWHUID]*UD¿FDIRUPXODULR import java.awt.BorderLayout; import javax.swing.JLabel; import javax.swing.JTabbedPane; import javax.swing.WindowConstants; public class FFormulario extends javax.swing.JFrame { private JLabel labelTitulo; private PDatosBasicos panelDatosBasicos; private PDatosContacto panelDatosContacto; private PDatosUbicacion panelDatosUbicacion; private PPasatiempos panelPasatiempos; private PBotones panelBotones; private JTabbedPane panelPestanas; public static void main(String[] args) { FFormulario frame = new FFormulario(); frame.setVisible(true); } public FFormulario() { initGUI(); labelTitulo = new JLabel(); labelTitulo.setText(“Formulario Usuario”); labelTitulo.setHorizontalAlignment(JLabel.CENTER); panelDatosBasicos = new PDatosBasicos(); panelDatosContacto = new PDatosContacto(); panelDatosUbicacion = new PDatosUbicacion(); panelPasatiempos = new PPasatiempos(); panelBotones = new PBotones(); panelPestanas = new JTabbedPane(); getContentPane().add(labelTitulo, BorderLayout.NORTH); getContentPane().add(panelPestanas, BorderLayout.CENTER); 216 Interfaz gráfica de usuario (GUI) { panelPestanas.addTab( “Datos Basicos”, panelDatosBasicos); panelPestanas.addTab( “Datos Contacto”, panelDatosContacto); panelPestanas.addTab( “Datos Ubicacion”, panelDatosUbicacion); panelPestanas.addTab(“Pasatiempos”, panelPasatiempos); PR R O EP H I R BI O D D O U C IR } getContentPane().add(panelBotones, BorderLayout.SOUTH); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setLayout(new BorderLayout()); setTitle(“Formulario”); setSize(400, 300); } } En la implementación se pueden apreciar los siguientes detalles: x El frame contiene un border layout en el que se agregan, un panel de título en el norte, un panel de pestañas en el centro y un panel de botones en el sur. x ϐϔ ϐ que quedaran organizados en el centro y linealmente. x La información en el panel de pestañas se ha dividido por medio de paneles independientes los cuales contienen los datos básicos, datos de contacto, datos de ubicación, los ϐ grid layout y un panel de datos ǡ ϐ ϔǤ Esta organización de elementos permite una cómoda visualización y proporciona un gran conjunto de atributos para la manipulación del usuario. Los resultados de esta implementación en cada una de las pestañas ͷͳǤ 217 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java 218 PR R O EP H I R BI O D D O U C IR Interfaz gráfica de usuario (GUI) Figura 51. Diseño de Formulario 219 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández 11.7 Manejo de eventos ϐ los comportamientos necesarios, para cada uno de los componentes de acuerdo a sus características. PR R O EP H I R BI O D D O U C IR 11.7.1 $FWLRQ/LVWHQHU La interfaz ActionListener permite ejecutar un método denominado actionPerformed, en el momento en que se da un evento de clic sobre un componente. El componente recibe la implementación del ActionListener mediante el método addActionListener. Es necesario implementar el método actionPerformed, el cual recibe un parámetro ActionEvent que contiene información del componente que ha invocado el evento. Este método se encuentra disponible en las clases JButton, JRadioButton, JCheckBox, JComboBox y JTextField. Con base en un botón, la sintaxis para implementar un evento actionPerformed es la siguiente: JButton boton = new JButton(); boton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { botonActionPerformed(evt); } }); private void botonActionPerformed(ActionEvent evt) { //Código para el evento } 11.7.2 .H\/LVWHQHU La interfaz KeyListener permite ejecutar tres métodos denominados keyTyped, keyReleased y keyPressed. El método keyTyped se invoca cuando se digita, es decir, oprime y suelta una tecla; el método keyRealeased se invoca cuando se suelta una tecla y el método keyPressed se invoca cuando se presiona una tecla. El componente 220 Interfaz gráfica de usuario (GUI) recibe la implementación del KeyListener a través de la instancia de la clase KeyAdapter, mediante el método addKeyListener. Es necesario implementar el método keyType, keyReleased y keyPressed; los cuales reciben un parámetro KeyEvent que contiene información del componente que ha invocado el evento. Este método se encuentra disponible en las clases JButton, JRadioButton, JCheckBox, JComboBox, JLabel, JList, JTextField, JTextArea, JTable y JPanel. PR R O EP H I R BI O D D O U C IR Con base en un cuadro de texto, la sintaxis para implementar los eventos keyTyped, keyReleased y keyPressed es la siguiente: JTectField cuadroTexto = new JTextField(); cuadroTexto.addKeyListener(new KeyAdapter() { public void keyTyped(KeyEvent evt) { cuadroTextoKeyTyped(evt); } public void keyReleased(KeyEvent evt) { cuadroTextoKeyReleased(evt); } public void keyPressed(KeyEvent evt) { cuadroTextoKeyPressed(evt); } }); private void cuadroTextoKeyPressed(KeyEvent evt) { //Código para el evento } private void cuadroTextoKeyReleased(KeyEvent evt) { //Código para el evento } private void cuadroTextoKeyTyped(KeyEvent evt) { //Código para el evento } 11.7.3 )RFXV/LVWHQHU La interfaz FocusListener permite ejecutar dos métodos denominados focusLost y focusGained. El método focusLost se invoca cuando un componente pierde el foco, es decir, cuando este componente deja 221 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR de estar seleccionado y el método focusGained se invoca cuando un componente adquiere el foco, es decir, cuando este componente se selecciona. El componente recibe la implementación del FocusListener a través de la instancia de la clase FocusAdapter mediante el método addFocusListener. Es necesario implementar el método focusLost y focusGained, los cuales reciben un parámetro FocusEvent que contiene información del componente que ha invocado el evento. Este método se encuentra disponible en todos los componentes de Swing. Con base en un cuadro de texto, la sintaxis para implementar los eventos focusLost y focusGained es la siguiente: cuadroTexto = new JTextField(); cuadroTexto.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent evt) { cuadroTextoFocusLost(evt); } public void focusGained(FocusEvent evt) { cuadroTextoFocusGained(evt); } }); private void cuadroTextoFocusGained(FocusEvent evt) { //Código para el evento } private void cuadroTextoFocusLost(FocusEvent evt) { //Código para el evento } 11.7.4 0RXVH/LVWHQHU La interfaz MouseListener permite ejecutar tres métodos denominados mouseClicked, mouseReleased y mousePressed. El método mouseClicked se invoca cuando se oprime y suelta un botón del mouse, el método mouseReleased se invoca cuando se suelta un botón del mouse y el método mousePressed se invoca cuando se presiona un botón del mouse. El componente recibe la implementación del MouseListener a través de la instancia de la clase MouseAdapter mediante el método addMouseListener. Es necesario implementar el método mouseClicked, mouseReleased y mousePressed; los cuales reciben un 222 Interfaz gráfica de usuario (GUI) parámetro MouseEvent que contiene información del componente que ha invocado el evento. Este método se encuentra disponible en todos los componentes de Swing. Con base en un panel, la sintaxis para implementar los eventos mouseClicked, mouseReleased y mousePressed es la siguiente: PR R O EP H I R BI O D D O U C IR JPanel panel = new JPanel(); panel.addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent evt) { panelMouseReleased(evt); } public void mousePressed(MouseEvent evt) { panelMousePressed(evt); } public void mouseClicked(MouseEvent evt) { panelMouseClicked(evt); } }); private void panelMouseClicked(MouseEvent evt) { //Código para el evento } private void panelMousePressed(MouseEvent evt) { //Código para el evento } private void panelMouseReleased(MouseEvent evt) { //Código para el evento } 11.7.5 0RXVH0RWLRQ/LVWHQHU La interfaz MouseMotionListener permite ejecutar dos métodos denominadosmouseDragged y mouseMoved. El método mouseDragged se invoca cuando se arrastra el puntero del mouse sobre el componente, esto quiere decir, que se mueve el puntero mientras está oprimido cualquier botón del mouse y el método mouseMoved se invoca cuando se mueve el puntero del mouse sobre el componente. El componente recibe la implementación del MouseMotionListener a través de la instancia de la clase MouseMotionAdapter, mediante el método addMouseMotionListener. Es necesario implementar 223 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández el método mouseDragged y mouseMoved, los cuales reciben un parámetro MouseEvent que contiene información del componente que ha invocado el evento. Este método se encuentra disponible en todos los componentes de Swing. Con base en un panel, la sintaxis para implementar los eventos mouseDragged y mouseMoved es la siguiente: PR R O EP H I R BI O D D O U C IR JPanel panel = new JPanel(); panel.addMouseMotionListener(new MouseMotionAdapter() { public void mouseMoved(MouseEvent evt) { panelMouseMoved(evt); } public void mouseDragged(MouseEvent evt) { panelMouseDragged(evt); } }); private void panelMouseDragged(MouseEvent evt) { //Código para el evento } private void panelMouseMoved(MouseEvent evt) { //Código para el evento } 11.8 Menús Los menús en Java se comportan de forma similar a los botones debido a que poseen la misma clase de eventos. Para crear una barra de menú funcional es necesario crear una barra de menú a través de la clase JMenuBar. La barra de menú se compone de JMenu, los cuales son menús que no deben contener eventos sino que permite desplegar JMenuItem, que permiten implementar eventos para proporcionar servicios a la aplicación. Existen otro tipo de menús que pueden ser utilizados para maximizar la funcionalidad de la aplicación como JCheckBoxMenuItem y JRadioButtonMenuItem. 224 Interfaz gráfica de usuario (GUI) ± × ï ϐ ± JPopUpMenu, el cual posee las mismas ventajas al JMenuBar. 11.8.1 -0HQX%DU PR R O EP H I R BI O D D O U C IR El JMenuBar proporciona una barra de menú, la cual se comporta como un contenedor de menús. Una barra de menú, necesariamente, debe agregarse a un JFrame. La sintaxis para crear y asignar una barra de menú es la siguiente: JMenuBar menuBar = new JMenuBar(); this.setJMenuBar(menuBar); Donde el apuntador this hace referencia al JFrame en donde se crea la barra de menú. 11.8.2 -0HQX, -0HQX,WHP y -0HQX6HSDUDWRU El JMenu proporciona un menú, el cual puede contener más, JMenu o JMenuItem. El menú debe agregarse a otro menú o a una barra de menú a través del método add. Un JMenu puede contener un ícono, el cual puede ser una imagen con extensión jpg, gif, png o ico. La imagen debe encontrarse en una carpeta dentro del proyecto. Para asignar la imagen a un menú es necesario usar el método setIcon, en el cual se envía como parámetro la sentencia getClass().getClassLoader().getResource(“img/nuevo. png”)). En este caso, el ícono se denomina nuevo.png. La sintaxis para crear y asignar un menú es la siguiente: JMenu menuArchivo = new JMenu(); barraMenu.add(menuArchivo); menuArchivo.setText(“Archivo”); JMenu menuNuevo = new JMenu(); mArchivo.add(menuNuevo); menuNuevo.setText(“Nuevo”); menuNuevo.setIcon(new ImageIcon(“img/ayuda.png”)); 225 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Donde menuNuevo está contenido en menuArchivo y este, en la barra de menú. Además, menuNuevo contiene un ícono que acompaña al texto del menú. El JMenuItem ï ϐǡ servicios. El menú ítem debe agregarse necesariamente a un menú, a través del método add. PR R O EP H I R BI O D D O U C IR La sintaxis para crear y asignar un menú ítem e implementar un evento para el menú ítem es la siguiente: JMenuItem menuItemArchivoSecuencial = new JMenuItem(); mNuevo.add(menuItemArchivoSecuencial); menuItemArchivoSecuencial.setText(“Archivo Secuencial”); menuItemArchivoSecuencial.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { menuItemArchivoSecuencialActionPerformed(evt); } }); private void menuItemArchivoSecuencialActionPerformed( ActionEvent evt) { //Código para el evento } El JSeparator permite colocar una línea de separación entre menús. La sintaxis para crear y asignar un separador es la siguiente: JSeparator separador1 = new JSeparator(); menuArchivo.add(separador1); El siguiente ejemplo implementa una barra de menú con diferentes menús y menú ítems. SDFNDJHLQWHUID]*UD¿FDPHQX import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; 226 Interfaz gráfica de usuario (GUI) import javax.swing.JSeparator; import javax.swing.WindowConstants; PR R O EP H I R BI O D D O U C IR public class FPrincipal extends JFrame { private JMenuBar menuBar; private JMenu menuAyuda; private JMenu menuNuevo; private JMenuItem menuItemCerrar; private JSeparator separador1; private JMenuItem menuItemArchivoSerializable; private JMenuItem menuItemArchivoSecuencial; private JMenu menuContenido; private JMenu menuAbrir; private JMenu menuArchivo; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( this.setTitle(“Frame Principal”); { menuBar = new JMenuBar(); setJMenuBar(menuBar); { menuArchivo = new JMenu(); menuBar.add(menuArchivo); menuArchivo.setText(“Archivo”); { menuNuevo = new JMenu(); menuArchivo.add(menuNuevo); menuNuevo.setText(“Nuevo”); { menuItemArchivoSecuencial = new JMenuItem(); menuNuevo.add(menuItemArchivoSecuencial); menuItemArchivoSecuencial.setText( “Archivo Secuencial”); menuItemArchivoSecuencial.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent evt) { menuItemArchivoSecuencialAction 227 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Performed(evt); } }); } { menuItemArchivoSerializable = new JMenuItem(); menuNuevo.add(menuItemArchivoSerializable); menuItemArchivoSerializable.setText( “Archivo Serializable”); PR R O EP H I R BI O D D O U C IR } } { menuAbrir = new JMenu(); menuArchivo.add(menuAbrir); menuAbrir.setText(“Abrir”); } { separador1 = new JSeparator(); menuArchivo.add(separador1); } { menuItemCerrar = new JMenuItem(); menuArchivo.add(menuItemCerrar); menuItemCerrar.setText(“Cerrar”); } } { menuAyuda = new JMenu(); menuBar.add(menuAyuda); menuAyuda.setText(“Ayuda”); menuAyuda.setIcon(new ImageIcon(“img/ayuda.png”)); { menuContenido = new JMenu(); menuAyuda.add(menuContenido); menuContenido.setText(“Contenido”); } } } setSize(400, 300); } private void menuItemArchivoSecuencialActionPerformed(ActionE vent evt) { //Código para el evento del menu item } } El resultado es el siguiente: 228 PR R O EP H I R BI O D D O U C IR Interfaz gráfica de usuario (GUI) Figura 52. JMenuBar, JMenu y JMenuItem ϐ À ïAyuda se ve bastante bien. Con base en ello se recomienda que las imágenes de los menús tengan una resolución de 16 x 16 píxeles. 11.8.3 -&KHFN%R[0HQX,WHP y -5DGLR%XWWRQ0HQX,WHP El JCheckBoxMenuItem permite colocar un CkeckBox en un menú. Esta característica es muy típica en menús que permitan la visualización particular de algún componente, como la barra de herramientas o la barra de estado. La sintaxis para crear y asignar un JCheckBoxMenuItem es la siguiente: JCheckBoxMenuItem checkMenuItemBarraEstado = new JCheckBoxMenuItem(); menu.add(checkMenuItemBarraEstado); checkMenuItemBarraEstado.setText(“Barra de Estado”); El JRadioButtonMenuItem permite colocar un Button en un menú. Esta característica es muy típica en menús que permitan la 229 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández visualización particular de algún componente, como la barra de herramientas o la barra de estado. La sintaxis para crear y asignar un JCheckBoxMenuItem es la siguiente: JRadioButtonMenuItem radioMenuItemVistaMiniatura = new JRadioButtonMenuItem(); menu.add(radioMenuItemVistaMiniatura); radioMenuItemVistaMiniatura.setText(“Vista en miniatura”); PR R O EP H I R BI O D D O U C IR El siguiente ejemplo implementa una barra de menú con diferentes menús ítems. SDFNDJHLQWHUID]*UD¿FDPHQX import javax.swing.ButtonGroup; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JRadioButtonMenuItem; import javax.swing.JSeparator; import javax.swing.WindowConstants; public class FPrincipal2 extends javax.swing.JFrame { private JMenuBar menuBar; private JMenu menuVer; private ButtonGroup buttonGroup; private JRadioButtonMenuItem radioMenuItemLista; private JRadioButtonMenuItem radioMenuItemIconos; private JRadioButtonMenuItem radioMenuItemMosaico; private JRadioButtonMenuItem radioMenuItemVistaMiniatura; private JSeparator separador1; private JCheckBoxMenuItem checkMenuItemBarraEstado; public static void main(String[] args) { FPrincipal2 frame = new FPrincipal2(); frame.setVisible(true); } public FPrincipal2() { initGUI(); } 230 private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( this.setTitle(“Frame Principal”); getContentPane().setLayout(null); { menuBar = new JMenuBar(); Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR setJMenuBar(menuBar); { menuVer = new JMenu(); menuBar.add(menuVer); menuVer.setText(“Ver”); { checkMenuItemBarraEstado = new JCheckBoxMenuItem(); menuVer.add(checkMenuItemBarraEstado); checkMenuItemBarraEstado.setText( “Barra de Estado”); } { separador1 = new JSeparator(); menuVer.add(separador1); } { radioMenuItemVistaMiniatura = new JRadioButtonMenuItem(); menuVer.add(radioMenuItemVistaMiniatura); radioMenuItemVistaMiniatura.setText( “Vista en miniatura”); } { radioMenuItemMosaico = new JRadioButtonMenuItem(); menuVer.add(radioMenuItemMosaico); radioMenuItemMosaico.setText(“Mosaico”); } { radioMenuItemIconos = new JRadioButtonMenuItem(); menuVer.add(radioMenuItemIconos); radioMenuItemIconos.setText(“Iconos”); } { radioMenuItemLista = new JRadioButtonMenuItem(); menuVer.add(radioMenuItemLista); radioMenuItemLista.setText(“Lista”); } buttonGroup = new ButtonGroup(); buttonGroup.add(radioMenuItemVistaMiniatura); buttonGroup.add(radioMenuItemMosaico); buttonGroup.add(radioMenuItemIconos); buttonGroup.add(radioMenuItemLista); } } setSize(400, 300); } } 231 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR El resultado es el siguiente: Figura 53. JMenuBar, JCheckBoxMenuItem y JRadioButtonMenuItem 11.8.4 JPopUpMenu El JPopUpMenu permite la creación de menús emergentes que serán visualizados al hacer clic con el botón secundario del mouse. Para que esta funcionalidad se presente es necesario hacer uso de la interfaz mouseListener, para poder crear los métodos mousePressed y mouseReleased. La sintaxis para crear y asignar un JPopUpMenu es la siguiente: JPopupMenu popUp = new JPopupMenu(); setComponentPopupMenu(this, popUp); El método setComponentPopupMenu es el siguiente: pDFNDJHLQWHUID]*UD¿FDPHQX import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; 232 Interfaz gráfica de usuario (GUI) import javax.swing.WindowConstants; public class FPrincipal3 extends JFrame { private JPopupMenu popUpMenu; private JMenuItem menuItemCopiar; private JMenuItem menuItemPegar; private JMenuItem menuItemCortar; PR R O EP H I R BI O D D O U C IR public static void main(String[] args) { FPrincipal3 frame = new FPrincipal3(); frame.setVisible(true); } public FPrincipal3() { initGUI(); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); { popUpMenu = new JPopupMenu(); setComponentPopupMenu(this, popUpMenu); { menuItemCopiar = new JMenuItem(); popUpMenu.add(menuItemCopiar); menuItemCopiar.setText(“Copiar”); } { menuItemPegar = new JMenuItem(); popUpMenu.add(menuItemPegar); menuItemPegar.setText(“Pegar”); } { menuItemCortar = new JMenuItem(); popUpMenu.add(menuItemCortar); menuItemCortar.setText(“Cortar”); } } setSize(400, 300); } SULYDWHYRLGVHW&RPSRQHQW3RSXS0HQX ¿QDO&RPSRQHQWSDUHQW ¿QDO-3RSXS0HQXPHQX ^ parent.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if(e.isPopupTrigger()) 233 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández menu.show(parent, e.getX(), e.getY()); } public void mouseReleased(MouseEvent e) { if(e.isPopupTrigger()) menu.show(parent, e.getX(), e.getY()); } }); } } PR R O EP H I R BI O D D O U C IR El resultado es el siguiente: Figura 54. PopUpMenu 11.9 Applets Un Applet es un contenedor similar a un JFrame con una gran variedad de aplicaciones. En un Applet se pueden realizar aplicaciones con todos los contenedores que se pueden usar en un JFrame. Los Applets tienen una característica adicional al JFrame que consiste en qué puede ser visualizado en una página web a través de lenguaje HTML. La máquina virtual de Java cuenta con una aplicación denominada “Applet Viewer”, la cual permite visualizar el Applet como una aplicación de escritorio. La sintaxis para implementar un Applet es la siguiente: 234 Interfaz gráfica de usuario (GUI) SDFNDJHLQWHUID]*UD¿FDDSSOHW import javax.swing.JApplet; public class MiApplet extends JApplet { public MiApplet() { initGUI(); } PR R O EP H I R BI O D D O U C IR private void initGUI() { //TODO codigo del Applet } } Al ejecutar el Applet se inicia la aplicación de Java Applet Viewer, ͷͷǤ Figura 55. Applet Viewer Al agregar algunos componentes se puede obtener una aplicación que pueda ser publicada en la web. La siguiente implementación presenta el factorial de un número ingresado, a través de un cuadro de texto. 235 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández SDFNDJHLQWHUID]*UD¿FDDSSOHW import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; PR R O EP H I R BI O D D O U C IR import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingConstants; public class Applet extends JApplet { private JLabel labelTitulo; private JButton botonCalcular; private JPanel panel; private JTextField textoNumero; public Applet() { initGUI(); } private void initGUI() { getContentPane().setLayout(new BorderLayout()); { labelTitulo = new JLabel(); getContentPane().add(labelTitulo, BorderLayout.NORTH); labelTitulo.setText(“Este es un Applet”); labelTitulo.setFont(new Font(“Tahoma”,1,16)); labelTitulo.setHorizontalAlignment( SwingConstants.CENTER); } { panel = new JPanel(); FlowLayout panelLayout = new FlowLayout(); getContentPane().add(panel, BorderLayout.CENTER); panel.setLayout(panelLayout); { textoNumero = new JTextField(); panel.add(textoNumero); textoNumero.setPreferredSize(new Dimension( 100, 20)); } { 236 Interfaz gráfica de usuario (GUI) botonCalcular = new JButton(); panel.add(botonCalcular); botonCalcular.setText(“Calcular Factorial”); botonCalcular.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent evt) { botonCalcularActionPerformed(evt); } }); } PR R O EP H I R BI O D D O U C IR } } private void botonCalcularActionPerformed(ActionEvent evt) { JOptionPane.showMessageDialog(this, “El factorial de “+ this.textoNumero.getText()+” es: “+ factorial(Integer.parseInt(this.textoNumero.getText())), ³0HQVDMH´-2SWLRQ3DQH,1)250$7,21B0(66$*( } private int factorial(int n){ return (n==1)?1:n*factorial(n-1); } } El resultado es el siguiente: Figura 56. Applet con componentes 237 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR ïͷ ×DzCalcular Factorial”, el resultado es el siguiente: Figura 57. Applet con componentes y cuadro de diálogo Para visualizar el Applet en una página web, se hace uso del tag “<applet></applet>” en donde se incluye el archivo ".class", generado por Java a través del atributo “code”. A este tag también se le puede ϐ ϐÀ Applet como “widthdzϐ ÀDzeight” para ϐÀǤ ×ǣ <html> <head> <title>Publicacion de Applet</title> </head> <body> <h3 align=”center” >APPLET PARA CALCULAR EL FACTORIAL PUBLICADO CON HTML</h3> <div align=”center”> <applet code=”Applet.class” height=”200” width=”200” border=”2”></applet> </div> </body> </html> 238 Interfaz gráfica de usuario (GUI) PR R O EP H I R BI O D D O U C IR El resultado presentado en un explorador de Internet es el siguiente: Figura 58. Applet publicado en página web Para lograr el resultado anterior es necesario que el archivo “Applet. class” se encuentre en la misma ubicación del archivo “Applet. html”. Al colocar un dato, hacer clic en el botón “Calcular Factorial”, el resultado es el siguiente: Figura 59. Applet publicado en página web con cuadro de diálogo En caso de que se requiera publicar un applet que usa clases, es necesario exportar todas las clases relacionadas a un archivo JARǤ ǡ ͷͻ À clases diferentes que se encuentran en paquetes diferentes. La implementación es la siguiente: 239 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Clase Applet SDFNDJHLQWHUID]*UD¿FDDSSOHW LPSRUWLQWHUID]*UD¿FDDSSOHWXWLO0DWHPDWLFDV PR R O EP H I R BI O D D O U C IR import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingConstants; public class Applet extends JApplet { private JLabel labelTitulo; private JButton botonCalcular; private JPanel panel; private JTextField textoNumero; public Applet() { initGUI(); } private void initGUI() { getContentPane().setLayout(new BorderLayout()); { labelTitulo = new JLabel(); getContentPane().add(labelTitulo, BorderLayout.NORTH); labelTitulo.setText(“Este es un Applet”); labelTitulo.setFont(new Font(“Tahoma”,1,16)); labelTitulo.setHorizontalAlignment( SwingConstants.CENTER); } { panel = new JPanel(); FlowLayout panelLayout = new FlowLayout(); getContentPane().add(panel, BorderLayout.CENTER); panel.setLayout(panelLayout); { textoNumero = new JTextField(); panel.add(textoNumero); textoNumero.setPreferredSize(new Dimension(100, 20)); } { botonCalcular = new JButton(); panel.add(botonCalcular); 240 Interfaz gráfica de usuario (GUI) botonCalcular.setText(“Calcular Factorial”); botonCalcular.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent evt) { botonCalcularActionPerformed(evt); } }); } } } PR R O EP H I R BI O D D O U C IR private void botonCalcularActionPerformed(ActionEvent evt) { JOptionPane.showMessageDialog(this, “El factorial de “+ this.textoNumero.getText()+” es: “+ Matematicas.factorial(Integer.parseInt( this.textoNumero.getText())), “Mensaje”, -2SWLRQ3DQH,1)250$7,21B0(66$*( } } Clase Matematicas SDFNDJHLQWHUID]*UD¿FDDSSOHWXWLO public class Matematicas { public static int factorial(int n){ return (n==1)?1:n*factorial(n-1); } } Archivo Applet.html <html> <head> <title>Publicacion de Applet</title> </head> <body> <h3 align=”center” >APPLET PARA CALCULAR EL FACTORIAL PUBLICADO CON HTML</h3> <div align=”center”> <applet archive=”Applet.jar” code= ´LQWHUID]*UD¿FDDSSOHW$SSOHWFODVV´KHLJKW ”200” width=”200” border=”2”></applet> </div> </body> </html> El resultado obtenido en este ejemplo es el mismo que en el caso anterior. Para lograr el resultado es necesario que el archivo “Applet. jar” se encuentre en la misma ubicación del archivo “Applet.html”. 241 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández 11.10 Ejercicios propuestos PR R O EP H I R BI O D D O U C IR 1. Implemente una aplicación MDI, aplicando arquitectura de tres capas, que contenga un formulario para ingresar información, uno para consultar y otro que permita visualizar un conjunto de datos en una tabla. Esta información debe encontrarse en un vector. El acceso a los diferentes formularios deben realizarse con base en menús. 2. Implemente una aplicación aplicando arquitectura de tres capas que permita almacenar un vector en un archivo serializable con base en JFileChooser. 3. Implemente un applet aplicando arquitectura de tres capas que permita almacenar un vector en un archivo serializable con base en JFileChooser. 4. Implemente una aplicación utilizando arquitectura de tres capas que permita almacenar y consultar información de un archivo secuencial, aplicando un InternalFrame para almacenar y otro InternalFrame para consultar. 242 CAPÍTULO 12 PR R O EP H I R BI O D D O U C IR $N¹ł?KO ϐ ϐ ǡ ǡ ǡ ǡ óvalos, polígonos y polilíneas. ϐ ǡǡ la mejor práctica es realzarlo sobre un JPanel. El JPanel contiene un método sobre escribible denominado Paint, que recibe un parámetro Graphics. En este método se debe realizar toda la implementación de dibujo de la aplicación. Para asegurar el bajo acoplamiento se recomienda aplicar una arquitectura, en donde, en su capa de presentación se cree una clase que herede de JPanel y en donde se implementen los diferentes algoritmos de dibujo. En este caso se debe incluir un JFrame y en allí incluir una referencia del JPanel que se agregaría al JFrame. Para agregar el JPanel al JFrame ϐ Layout al JFrame. Si no se le asigna Layout, por defecto, tendrá null, el cual permitiría agregar el JPanel Ó ×ϐǤ Lo más apropiado es agregar al JFrame Border Layout, de esa forma el JPanel quedará con tamaño dinámico, pero el dibujo tendrá que ser también dinámico. La implementación del JFrame es la siguiente: Clase PDibujo SDFNDJHJUD¿FDV import java.awt.Graphics; import javax.swing.JPanel; Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández public class PDibujo extends javax.swing.JPanel { public PDibujo() { } public void paint(Graphics g){ } PR R O EP H I R BI O D D O U C IR } Clase FPrincipal SDFNDJHJUD¿FDV import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private PDibujo panelDibujo; public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { FPrincipal inst = new FPrincipal(); inst.setLocationRelativeTo(null); inst.setVisible(true); } }); } public FPrincipal() { initGUI(); } } 244 private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( getContentPane().setLayout(new BorderLayout()); { panelDibujo = new PDibujo(); getContentPane().add( panelDibujo, BorderLayout.CENTER); } setSize(400, 300); } Gráficos 12.1 Clase Graphics PR R O EP H I R BI O D D O U C IR La clase Graphics permite realizar dibujos sobre el JPanel a través del método Paint. Esta clase está directamente relacionada con la clase Colorǡ±ϐ instancia de Graphics puede pintar. La clase Color proporciona colores del formato RGB, los cuales pueden ser incluidos en el constructor. ϐ se utilizan en computación. Estas coordenadas inician el (0,0) en la esquina superior izquierda y terminan en (x,y) en la esquina inferior derecha en donde x,y equivalen al ancho y alto del panel, Ǥ Ͳ Ǥ ͚͔ǤƤ 12.1.1 Formas de Graphics A través de la clase Graphics es posible dibujar una gran cantidad de formas como rectángulos, arcos, imágenes, textos, óvalos, polígonos y polilíneas. Línea Una línea se puede obtener mediante el siguiente método: drawLine(int x1, int y1, int x2, int y2) Este método dibuja una línea con un punto en la en la coordenada (x1,y1) y el otro punto en la coordenada (x2,y2). 245 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Rectángulo Un rectángulo se puede obtener mediante diferentes métodos como: drawRect(int x, int y, int width, int height) PR R O EP H I R BI O D D O U C IR Este método dibuja un rectángulo con la esquina superior izquierda en la coordenada (x,y). Tiene un ancho y alto dados por los parámetros width y height. Esto indica que la coordenada de la esquina inferior derecha es (x+width,y+height). drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) Este método dibuja un rectángulo con las mismas características de posición y tamaño del método drawRect. Adicionalmente, dibuja las esquinas redondeadas con base en los parámetros arcWidth y arcHeight. ¿OO5HFW LQW[LQW\LQWZLGWKLQWKHLJKW Este método dibuja un rectángulo con las mismas características de posición y tamaño del método drawRect. Adicionalmente, llena de color el rectángulo. ¿OO5RXQG5HFW LQW[LQW\LQWZLGWKLQWKHLJKWLQWDUF:LGWK int arcHeight) Este método dibuja un rectángulo con las mismas características de posición, tamaño y esquinas del método drawRoundRect. Adicionalmente, llena de color el rectángulo. Óvalo Un óvalo se puede obtener mediante diferentes métodos como: drawOval(int x, int y, int width, int height) Este método dibuja un óvalo con la esquina superior izquierda en la coordenada (x,y). Tiene un ancho y alto dados por los parámetros width y heigh. Esto indica que la coordenada de la esquina inferior derecha es (x+width,y+height). 246 Gráficos ¿OO2YDO LQW[LQW\LQWZLGWKLQWKHLJKW Este método dibuja un óvalo con las mismas características de posición y tamaño del método drawOval. Adicionalmente, llena de color el óvalo. Polígono PR R O EP H I R BI O D D O U C IR Un polígono se puede obtener mediante diferentes métodos como: drawPolygon(int[] xPoints, int[] yPoints, int nPoints) ±À ϐ xPoints y yPoints. La cantidad de puntos se incluyen en el parámetro nPoints. ¿OO3RO\JRQ LQW>@[3RLQWVLQW>@\3RLQWVLQWQ3RLQWV Este método dibuja un polígono con las mismas características de posición del método drawPoligon. Adicionalmente, llena de color el polígono. Cadenas de caracteres Una línea se puede obtener mediante el siguiente método: drawString(String str, int x, int y) Este método dibuja la cadena del parámetro str con la esquina inferior izquierda en la coordenada (x, y). Imágenes Una imagen se puede obtener mediante el siguiente método: drawImage(Image img, int x, int y, ImageObserver observer) Este método dibuja una imagen img con la esquina superior izquierda en la coordenada (x,y). El ImageObserver corresponde al contenedor que visualiza la imagen. 247 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Considerando un JPanel se pueden realizar diferentes formas desde el método Paint, que recibe por parámetro un objeto Graphics. Este JPanel debe ser incluido en un JFrame. Clase PDibujo SDFNDJHJUD¿FDVIRUPDV%DVLFDV PR R O EP H I R BI O D D O U C IR import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import javax.swing.JPanel; public class PDibujo extends JPanel { public void paint(Graphics g){ Color c; c=new Color(255,255,255); g.setColor(c); J¿OO5HFW JHW:LGWK JHW+HLJKW c=new Color(0,0,255); g.setColor(c); g.drawLine(10, 10, 10, 100); c=new Color(0,255,0); g.setColor(c); g.drawRect(20, 10, 50, 100); J¿OO5HFW g.drawRoundRect(140, 10, 50, 100, 20, 20); J¿OO5RXQG5HFW c=new Color(255,0,0); g.setColor(c); g.drawOval(260, 10, 50, 100); J¿OO2YDO c=new Color(255,0,255); g.setColor(c); int []x={10,20,30,40,50}; int []y={120,180,150,180,120}; g.drawPolygon(x, y, 5); int []x2={60,70,80,90,100}; 248 Gráficos int []y2={120,180,150,180,120}; J¿OO3RO\JRQ [\ c=new Color(100,100,100); g.setColor(c); Font f = new Font(“Tahoma”,10,25); g.setFont(f); g.drawString(“Hola mundo”, 120, 150); PR R O EP H I R BI O D D O U C IR Image image = Toolkit.getDefaultToolkit().getImage( “img/java.jpg”); g.drawImage(image, 280, 120, this); } } Clase FPrincipal SDFNDJHJUD¿FDVIRUPDV%DVLFDV import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private PDibujo panelDibujo; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); panelDibujo = new PDibujo(); getContentPane().add(panelDibujo, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(new BorderLayout()); setSize(400, 300); } } 249 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández En esta aplicación dibuja las siguientes formas: x Una línea con el primer punto en las coordenadas (10,10) y el segundo punto en las coordenadas (10,100). PR R O EP H I R BI O D D O U C IR x Un rectángulo sin relleno con el punto superior izquierdo en las coordenadas (20,10) y el punto inferior derecho en las coordenadas (50,100). x Un rectángulo con relleno con el punto superior izquierdo en las coordenadas (80,10) y el punto inferior derecho en las coordenadas (50,100). x Un rectángulo sin relleno con el punto superior izquierdo en las coordenadas (140,10) y el punto inferior derecho en las coordenadas (50,100). Además, tiene bordes redondeados ʹͲÀǡ ǡ ʹͲÀ en el eje X como en Y. x Un rectángulo con relleno con el punto superior izquierdo en las coordenadas (200,10) y el punto inferior derecho en las coordenadas (50,100). Además, tiene bordes redondeados ʹͲÀǡ ǡ ʹͲÀ en el eje X como en Y. x Un óvalo sin relleno con el punto superior izquierdo en las coordenadas (260,10) y el punto inferior derecho en las coordenadas (50,100). Esto indica que el óvalo tiene su punto máximo superior en la coordenada Y=10, su punto máximo a la izquierda en la coordenada X=260, su punto máximo inferior en la coordenada Y=10+100=110 y su punto máximo αʹͲΪͷͲα͵ͳͲǤ x Un óvalo con relleno con el punto superior izquierdo en las coordenadas (320,10) y el punto inferior derecho en las coordenadas (50,100). 250 Gráficos x À ͷǤ x À ͷ Ǥ x Dz dzǡ Ó ʹͷ píxeles en la coordenada inferior izquierda (120,150). PR R O EP H I R BI O D D O U C IR x Una imagen del logotipo de Java en la coordenada (280,120). El resultado es como se presenta en la Figura 61. Figura 61. Formas de Graphics 12.1.2 Paneles estáticos y dinámicos Si se desea pintar una cuadrícula de color gris colocando de fondo color blanco, se podría realizar la siguiente implementación en la clase PDibujo ×ǡ͵Ͳ À ʹͶͲÀ ϐ×± setBounds. Esta implementación utiliza el método ϔ para pintar un cuadrado blanco del tamaño del panel y el método drawLine para pintar cada línea en el panel. 251 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Clase PDibujo SDFNDJHJUD¿FDVSDQHO(VWDWLFR import java.awt.Color; import java.awt.Graphics; import javax.swing.JPanel; PR R O EP H I R BI O D D O U C IR public class PDibujo extends JPanel { public void paint(Graphics g){ Color c; c=new Color(255,255,255); g.setColor(c); J¿OO5HFW c=new Color(180,180,180); g.setColor(c); int i; for(i=36; i<360; i+=36){ g.drawLine(i, 0, i, 240); } for(i=24; i<240; i+=24){ g.drawLine(0, i, 360, i); } } } Clase FPrincipal SDFNDJHJUD¿FDVSDQHO(VWDWLFR import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private PDibujo panelDibujo; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } 252 Gráficos public FPrincipal() { initGUI(); panelDibujo = new PDibujo(); panelDibujo.setBounds(10, 10, 360, 240); getContentPane().add(panelDibujo); } PR R O EP H I R BI O D D O U C IR private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(null); setSize(400, 300); } } El resultado es como se muestra en la Figura 62. Figura 62. Ƥ À En esta implementación, la cuadrícula es estática debido a que el tamaño del panel también lo es. El tamaño de cada celda entonces ͵ʹͶÀ À ͳͲϐͳͲ columnas. Esta implementación genera un defecto que consiste en 253 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández que al maximizar o cambiar de tamaño el JFrameǡ ϐ adapta al nuevo tamaño. ϐ Layout del JFrame a Border Layout se obtiene un panel dinámico y su cuadrícula también lo sería. La implementación de las dos clases es la siguiente: PR R O EP H I R BI O D D O U C IR Clase PDibujo SDFNDJHJUD¿FDVSDQHO'LQDPLFR import java.awt.Color; import java.awt.Graphics; import javax.swing.JPanel; public class PDibujo extends JPanel { private int ancho; private int alto; } 254 public void paint(Graphics g){ this.ancho=(int)this.getSize().getWidth(); this.alto=(int)this.getSize().getHeight(); int anchoCelda=(int)(this.getSize().getWidth()/10); int altoCelda=(int)(this.getSize().getHeight()/10); Color c; c=new Color(255,255,255); g.setColor(c); J¿OO5HFW WKLVDQFKRWKLVDOWR c=new Color(180,180,180); g.setColor(c); int i; for(i=anchoCelda; i<this.ancho-anchoCelda; i+ =anchoCelda){ g.drawLine(i, 0, i, this.alto); } for(i=altoCelda; i<this.alto-altoCelda; i+=altoCelda){ g.drawLine(0, i, this.ancho, i); } } Gráficos Clase FPrincipal SDFNDJHJUD¿FDVSDQHO'LQDPLFR import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.WindowConstants; PR R O EP H I R BI O D D O U C IR public class FPrincipal extends JFrame { private PDibujo panelDibujo; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); panelDibujo = new PDibujo(); getContentPane().add(panelDibujo, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(new BorderLayout()); setSize(400, 300); } } En este caso se debe calcular el ancho y alto del panel a través de los métodosgetSize().getWidth() y getSize().getHeight(). Así mismo, el alto y ancho de cada celda, el cual corresponde al ancho y alto del ͳͲǡï Ǥ debe hacer casting a int, debido a que el método drawLine recibe en sus parámetros este tipo de dato. De esta forma, al cambiar el tamaño del Frame, automáticamente cambia el tamaño de la cuadrícula. ͵Ǥ 255 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java ͚͗Ǥ Ƥ À 12.2 Gráficas de señales ϐ Ó ǡ una capa de lógica de negocio que contenga las clases seno y coseno. Sin embargo, para asegurar escalabilidad al proyecto se debería crear una clase abstracta llamada “Senal” que herede atributos y métodos necesarios para el dibujo. La implementación es la siguiente: Clase Senal SDFNDJHJUD¿FDVVHQDOHVORJLFD public abstract class Senal { protected int amplitud; protected int frecuencia; protected int offset; public Senal(int a, int f,int o){ this.amplitud=a; this.frecuencia=f; this.offset=o; } public int getAmplitud() { return amplitud; 256 Gráficos } public void setAmplitud(int amplitud) { this.amplitud = amplitud; } public int getFrecuencia() { return frecuencia; } PR R O EP H I R BI O D D O U C IR public void setFrecuencia(int frecuencia) { this.frecuencia = frecuencia; } public int getOffset() { return offset; } public void setOffset(int offset) { this.offset = offset; } public abstract int[] calcular(int ancho, int alto); } Clase Seno SDFNDJHJUD¿cas.senales.logica; public class Seno extends Senal { public Seno(int a, int f,int o){ super(a,f,o); } @Override public int[] calcular(int ancho, int alto){ int [] puntos = new int[ancho]; for(int i=0;i<ancho;i++){ puntos[i]=(this.offset*alto/10)+(int)((alto/10) *this.amplitud* Math.sin(Math.PI/180*i *this.frecuencia)); } return puntos; } } 257 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Clase Coseno SDFNDJHJUD¿FDVVHQDOHVORJLFD public class Coseno extends Senal { public Coseno(int a, int f,int o){ super(a,f,o); } PR R O EP H I R BI O D D O U C IR @Override public int[] calcular(int ancho, int alto){ int [] puntos = new int[ancho]; for(int i=0;i<ancho;i++){ puntos[i]=(this.offset*alto/10)+(int)((alto/10) *this.amplitud* Math.cos(Math.PI/180*i*this.frecuencia)); } return puntos; } } Las clases Seno y Coseno implementan un método llamado calcular que retorna un arreglo de puntos. Estos puntos son los valores de la señal con la amplitud, frecuencia y offset (desfase en el eje Y) asignados a través del constructor. Los parámetros ancho y alto indican la cantidad de píxeles del panel, debido a que este es dinámico. Los puntos de la señal se calculan haciendo un proceso iterativo que depende del número de píxeles en el eje X. Los puntos dependen del nivel de offset ͳͲ À ͳͲϐǤ offset se le suma la señal, cuya amplitud se multiplica por el atributo correspondiente ͳͲǡ ϐ Ó Y ϐ À Ǥ Ó seno y coseno reciben por parámetro el ángulo en radianes, por lo que se debe realizar la conversión a frecuencia multiplicando por pi ͳͺͲǤ El JFrame, entonces, debe cambiar para ofrecer un mecanismo que asigne valores a las señales. En este caso se proponen tres cuadros de texto para los valores, un botón para dibujar la señal seno y un botón para dibujar la señal coseno. Para estos controles, lo más apropiado 258 Gráficos es crear una clase que extienda de JPanel. Así mismo, se requiere una clase para dibujar que extienda de JPanel que contenga el método Paint. El frame debe tener objetos que sean instancias de estas clases, de esta forma, para que el panel de controles acceda al panel de dibujo es necesario que el panel de controles tenga una referencia del frame. PR R O EP H I R BI O D D O U C IR La implementación es la siguiente: Clase FPrincipal SDFNDJHJUD¿FDVVHQDOHVSUHVHQWDFLRQ LPSRUWJUD¿FDVVHQDOHVORJLFD&RVHQR LPSRUWJUD¿FDVVHQDOHVORJLFD6HQDO LPSRUWJUD¿FDVVHQDOHVORJLFD6HQR import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.SwingConstants; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private JLabel labelTitulo; private PDibujo panelDibujo; private PControles panelControles; private Senal senal; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( getContentPane().setLayout(new BorderLayout()); this.setTitle(“Senales Trigonometricas”); { labelTitulo = new JLabel(); getContentPane().add(labelTitulo, BorderLayout.NORTH); 259 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández labelTitulo.setText(“SENALES TRIGONOMETRICAS”); labelTitulo.setFont(new java.awt.Font(“Tahoma”,1,16)); labelTitulo.setHorizontalAlignment( SwingConstants.CENTER); } { panelDibujo = new PDibujo(); getContentPane().add(panelDibujo, BorderLayout.CENTER); PR R O EP H I R BI O D D O U C IR } { panelControles = new PControles(this); getContentPane().add(panelControles, BorderLayout.SOUTH); } setSize(400, 300); } public void pintarSeno(int amplitud, int frecuencia, int offset){ senal=new Seno(amplitud, frecuencia, offset); panelDibujo.actualizar(senal); } public void pintarCoseno(int amplitud, int frecuencia, int offset){ senal=new Coseno(amplitud, frecuencia, offset); panelDibujo.actualizar(senal); } } Clase PControles SDFNDJHJUD¿FDVVHQDOHVSUHVHQWDFLRQ import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; public class PControles extends JPanel { private FPrincipal framePrincipal; private JLabel labelAmplitud; private JTextField textAmplitud; private JLabel labelFrecuencia; 260 Gráficos private JTextField textFrecuencia; private JLabel labelOffset; private JTextField textOffset; private JButton buttonSeno; private JButton buttonCoseno; public PControles(FPrincipal framePricipal) { initGUI(); this.framePrincipal = framePricipal; } PR R O EP H I R BI O D D O U C IR private void initGUI() { { labelAmplitud = new JLabel(); add(labelAmplitud); labelAmplitud.setText(“Amplitud”); } { textAmplitud = new JTextField(); add(textAmplitud); textAmplitud.setText(“1”); textAmplitud.setPreferredSize(new Dimension(20, 20)); } { labelFrecuencia = new JLabel(); add(labelFrecuencia); labelFrecuencia.setText(“Frecuencia”); } { textFrecuencia = new JTextField(); add(textFrecuencia); textFrecuencia.setText(“10”); textFrecuencia.setPreferredSize(new Dimension(20, 20)); } { labelOffset = new JLabel(); add(labelOffset); labelOffset.setText(“Offset”); } { textOffset = new JTextField(); add(textOffset); textOffset.setText(“0”); textOffset.setPreferredSize(new Dimension(20, 20)); } { buttonSeno = new JButton(); add(buttonSeno); buttonSeno.setText(“Seno”); buttonSeno.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { 261 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández buttonSenoActionPerformed(evt); } }); } { PR R O EP H I R BI O D D O U C IR buttonCoseno = new JButton(); add(buttonCoseno); buttonCoseno.setText(“Coseno”); buttonCoseno.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { buttonCosenoActionPerformed(evt); } }); } } private void buttonSenoActionPerformed(ActionEvent evt) { int amplitud = Integer.parseInt(textAmplitud.getText()); int frecuencia = Integer.parseInt( textFrecuencia.getText()); int offset = Integer.parseInt(textOffset.getText()); framePrincipal.pintarSeno(amplitud, frecuencia, offset); } private void buttonCosenoActionPerformed(ActionEvent evt) { int amplitud = Integer.parseInt(textAmplitud.getText()); int frecuencia = Integer.parseInt( textFrecuencia.getText()); int offset = Integer.parseInt(textOffset.getText()); framePrincipal.pintarCoseno(amplitud, frecuencia, offset); } } Clase PDibujo SDFNDJHJUD¿FDVVHQDOHVSUHVHQWDFLRQ LPSRUWJUD¿FDVVHQDOHVORJLFD6HQDO import java.awt.Color; import java.awt.Graphics; import javax.swing.JPanel; public class PDibujo extends JPanel { private int ancho; private int alto; private Senal senal; 262 Gráficos public void actualizar(Senal senal){ this.senal=senal; this.repaint(); } PR R O EP H I R BI O D D O U C IR public void paint(Graphics g){ this.ancho=(int)this.getSize().getWidth(); this.alto=(int)this.getSize().getHeight(); int anchoCelda=(int)(this.getSize().getWidth()/10); int altoCelda=(int)(this.getSize().getHeight()/10); Color c; c=new Color(255,255,255); g.setColor(c); J¿OO5HFW WKLVDQFKRWKLVDOWR c=new Color(180,180,180); g.setColor(c); int i; for(i=anchoCelda; i<this.ancho-(anchoCelda/2); i+ =anchoCelda){ g.drawLine(i, 0, i, this.alto); } for(i=altoCelda; i<this.alto-(altoCelda/2); i+=altoCelda){ g.drawLine(0, i, this.ancho, i); } c=new Color(0,0,255); g.setColor(c); if(this.senal!=null){ int []puntos = this.senal.calcular(this.ancho,this.alto); for(i=0;i<this.ancho-1; i++){ g.drawLine(i, (this.alto/2)-puntos[i], i+1, ( this.alto/2)-puntos[i+1]); } } } } Las anteriores clases presentan las siguientes características: x El frame ϐ Ǥ x El frame tiene un panel en el sur con los componentes necesarios para enviar los parámetros de amplitud, frecuencia y offset de las señales. x El panel PControles posee un método para el botón Seno que hace un llamado al metido pintarSeno que crea un objeto instancia de la clase Seno en la capa de lógica, al que se le envía por el constructor los valores de amplitud, frecuencia y offset. 263 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Este método envía el objeto al objeto panelDibujo a través del método actualizar. PR R O EP H I R BI O D D O U C IR x El panel PControles posee un método para el botón Coseno que hace un llamado al metido pintarCoseno que crea un objeto instancia de la clase Coseno en la capa de lógica, al que se le envía por el constructor los valores de amplitud, frecuencia y offset. Este método envía el objeto al objeto panelDibujo a través del método actualizar. x El panel PDibujo tiene un método actualizar que asigna el objeto senal. x El panel PDibujo tiene un método Paint que coloca el fondo blanco al panel, la cuadrícula y dibuja la senal basado en los puntos retornados por Seno y CosenoǤϐ en pintar un conjunto de líneas desde un punto hasta el punto siguiente. El método drawLine permite dibujar las líneas en mención. Los parámetros del eje Y, tienen un valor que depende ǡ ϐ senal en la mitad. ϐͶͷǤ Figura 64. Dibujo de la senal Seno 264 PR R O EP H I R BI O D D O U C IR Gráficos Figura 65. Dibujo de la senal Coseno 12.3 Clase Graphics2D La clase Graphics2D permite una gran cantidad de funcionalidades sobre las formas que se pintan en un JPanel. Entre estas funcionalidades se encuentran degradado, transparencia y rotación, entre otros. Graphics2D es una subclase de Graphics lo que indica que un objeto Graphics puede ser convertido a un objeto Graphics2D. De esta forma, cuando se requiera utilizar un objeto de Graphics2D en un JPanel, se debe crear un objeto Graphics2D al cual se inicializa mediante un casting del objeto Graphics. La sintaxis es la siguiente: public void paint(Graphics g){ Graphics2D g2d = (Graphics2D)g; } 12.3.1 Degradado Para lograr un degradado es necesario utilizar el método setPaint de la clase Graphics2D. Este método debe recibir por parámetro un 265 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández objeto de la clase GradientPaint ϐ × degradado que se quiere asignar a las formas pintadas mediante Graphics2D. Por ejemplo, si se desea pintar una elipse de color negra con degradado diagonal, la implementación es la siguiente: Clase FPrincipal SDFNDJHJUD¿FDV'GHJUDGDGR PR R O EP H I R BI O D D O U C IR import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private PDibujo panelDibujo; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); panelDibujo = new PDibujo(); getContentPane().add(panelDibujo, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(new BorderLayout()); setSize(400, 300); } } Clase PDibujo SDFNDJHJUD¿FDV'GHJUDGDGR import java.awt.Color; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.Ellipse2D; import javax.swing.JPanel; 266 Gráficos public class PDibujo extends JPanel { public void paint(Graphics g){ Graphics2D g2d = (Graphics2D)g; GradientPaint gradient = new GradientPaint(0, 0, Color.black, getWidth(), getHeight(), Color.white, true); g2d.setPaint(gradient); JG¿OO2YDO JHW:LGWK JHW+HLJKW } PR R O EP H I R BI O D D O U C IR } El resultado se observa en la Figura 66. Figura 66. Degradado con Graphics2D 12.3.2 Transparencia Para lograr transparencia es necesario utilizar el método setComposite de la clase Graphics2D. Este método debe recibir por parámetro un objeto de la clase Composite. Este objeto se crea mediante la clase AlphaComposite en el método getInstance con el que se lleva a cabo la ϐ × Ǥǡ dos cuadrados superpuestos con transparencia, la implementación es la siguiente: 267 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Clase FPrincipal SDFNDJHJUD¿FDV'WUDQVSDUHQFLD import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.WindowConstants; PR R O EP H I R BI O D D O U C IR public class FPrincipal extends JFrame { private PDibujo panelDibujo; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); panelDibujo = new PDibujo(); getContentPane().add(panelDibujo, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(new BorderLayout()); setSize(400, 300); } } Clase PDibujo SDFNDJHJUD¿FDV'WUDQVSDUHQFLD import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private PDibujo panelDibujo; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } 268 Gráficos public FPrincipal() { initGUI(); panelDibujo = new PDibujo(); getContentPane().add(panelDibujo, BorderLayout.CENTER); } PR R O EP H I R BI O D D O U C IR private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(new BorderLayout()); setSize(400, 300); } } El resultado es el que aparece en la Figura 67. Figura 67. Transparencia con Graphics2D 12.3.3 Translación y rotación Para lograr translación es necesario utilizar el método “translate” de la clase “Graphics2D”. Este método debe recibir por parámetro las coordenadas de translación. Estas coordenadas equivalen al nuevo centro del objeto Graphics2D. Para lograr rotación es necesario utilizar el método “rotate” de la clase “Graphics2D”. Este método debe recibir 269 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández por parámetro el ángulo en radianes de rotación. Por ejemplo, si se desea pintar una palabra que rote sobre su eje, la implementación es la siguiente: Clase FPrincipal packDJHJUD¿FDV'URWDFLRQ7UDQVODFLRQ PR R O EP H I R BI O D D O U C IR import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.WindowConstants; public class FPrincipal extends JFrame { private PDibujo panelDibujo; public static void main(String[] args) { FPrincipal frame = new FPrincipal(); frame.setVisible(true); } public FPrincipal() { initGUI(); panelDibujo = new PDibujo(); getContentPane().add(panelDibujo, BorderLayout.CENTER); } private void initGUI() { VHW'HIDXOW&ORVH2SHUDWLRQ :LQGRZ&RQVWDQWV',6326(B21B&/26( setTitle(“Frame Principal”); getContentPane().setLayout(new BorderLayout()); setSize(400, 300); } } Clase PDibujo SDFNDJHJUD¿FDV'URWDFLRQ7UDQVODFLRQ import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JPanel; 270 Gráficos public class PDibujo extends JPanel { PR R O EP H I R BI O D D O U C IR public void paint(Graphics g){ Graphics2D g2d = (Graphics2D)g; g2d.translate(getWidth()/2, getHeight()/2); g2d.setFont(new Font(“Times”,10,50)); for(int i=0; i<8; i++){ g2d.setColor((i%2==0)?Color.BLACK:Color.BLUE); g2d.rotate(Math.PI/4); g2d.drawString(“Java”, 0, 0); } } } El resultado es el siguiente: Figura 68. Translación y rotación con Graphics2D 12.4 Gráficas estadísticas (Chart) Existen componentes desarrolladores por diferentes colaboradores × ϐ À Ǥ 271 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández componentes más conocidos es JFreeChart1. Este componente ×ϐ con base en un conjunto de datos que se proporcionan a través de ± Àϐ Ǥ PR R O EP H I R BI O D D O U C IR Para usar JFreeChart es necesario descargar el componente del sitio web e incluir en el proyecto como librería al menos los elementos presentados en la Figura 69. Figura 69. Referenced Libraries para JFreeChart 12.4.1 Diagramas de torta JFreeChart permite la creación de diagrama de torta (Pie Chart) en dos o tres dimensiones. Además, también permite almacenar el resultado en un archivo jpg. En el momento de crear un Pie Chart es necesario asignar los datos mediante la clase DefaultPieDataSet en el método setValue. Este método permite incluir un texto y un valor numérico por cada valor que contendrá el Pie Chart. Sin embargo, para pintar el Pie Chart es necesario realizar un casting a la clase PieDataSet. La clase PieDataSet es súper clase de DefaultPieDataSet. La sintaxis es la siguiente: DefaultPieDataset defaultDataSet = new DefaultPieDataset(); defaultDataSet.setValue(“Texto 1”, 40); defaultDataSet.setValue(“Texto 2”, 60); PieDataset dataSet = defaultDataSet; 1 272 http://www.jfree.org/jfreechart/ Gráficos Una vez asignados los datos se crea un chart mediante la clase ChartFactory. El chart debe tener un título, datos y puede tener ϐǤLa sintaxis es la siguiente: JFreeChart chart = ChartFactory.createPieChart(“Pie”, dataSet, true, true, true); PR R O EP H I R BI O D D O U C IR Posteriormente, el Pie Chart debe desplegarse mediante un ChartPanel. La sintaxis es la siguiente: ChartPanel panel = new ChartPanel(chart); JFreeChart también permite exportar el resultado como una imagen jpg. Para ello se debe tener un objeto de la clase File que indique el archivo en donde se almacenara la imagen, el chart y el tamaño en píxeles. La sintaxis es la siguiente: )LOH¿OH QHZ)LOH ³LPJSLHMSJ´ try { &KDUW8WLOLWLHVVDYH&KDUW$V-3(* ¿OHFKDUW } catch (IOException e) { e.printStackTrace(); } Ejemplo de Pie Chart 2D El siguiente código presenta un ejemplo de creación de un Pie Chart 2D con datos ingresados directamente en el código. La implementación es la siguiente: package charts.pie; import java.awt.BorderLayout; import java.io.File; import java.io.IOException; import javax.swing.JFrame; import javax.swing.WindowConstants; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.jfree.data.general.DefaultPieDataset; 273 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández import org.jfree.data.general.PieDataset; public class FPie2D extends JFrame { public static void main(String[] args) { FPie2D frame = new FPie2D(); frame.setVisible(true); } PR R O EP H I R BI O D D O U C IR public FPie2D() { initGUI(); PieDataset dataSet = new DefaultPieDataset(); dataSet = createDataSet(); JFreeChart chart = ChartFactory.createPieChart( “Uso de exploradores”, dataSet, true, true, true); ChartPanel panel = new ChartPanel(chart); )LOH¿OH QHZ)LOH ³LPJSLHMSJ´ try { &KDUW8WLOLWLHVVDYH&KDUW$V-3(* ¿OHFKDUW } catch (IOException e) { e.printStackTrace(); } getContentPane().add(panel, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setLayout(new BorderLayout()); setTitle(“JFreePie Chart 2D”); setSize(400, 300); } private PieDataset createDataSet() { DefaultPieDataset defaultDataSet = new DefaultPieDataset(); defaultDataSet.setValue(“Mozilla Firefox”, 40); defaultDataSet.setValue(“Google Chrome”, 25); defaultDataSet.setValue(“Internet Explorer”, 22); defaultDataSet.setValue(“Safari”, 8); defaultDataSet.setValue(“Opera”, 5); return defaultDataSet; } } Los resultados son los siguientes: 274 PR R O EP H I R BI O D D O U C IR Gráficos Figura 70. Pie Chart 2D Figura 71. Pie Chart 2D exportado como jpg 275 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández También se puede crear un Pie Chart͵ǤPie Chart 3D permite ǡ ϐ ×Ǥ × Pie Chart 3D con los mismos datos del ejemplo anterior es la siguiente: package charts.pie; import java.awt.BorderLayout; PR R O EP H I R BI O D D O U C IR import javax.swing.JFrame; import javax.swing.WindowConstants; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PiePlot3D; import org.jfree.data.general.DefaultPieDataset; import org.jfree.data.general.PieDataset; import org.jfree.util.Rotation; public class FPie3D extends JFrame { public static void main(String[] args) { FPie3D frame = new FPie3D(); frame.setVisible(true); } public FPie3D() { initGUI(); PieDataset dataSet = new DefaultPieDataset(); dataSet = createDataSet(); JFreeChart chart = ChartFactory.createPieChart3D( “Uso de exploradores”, dataSet, true, true, true); PiePlot3D plot = (PiePlot3D)chart.getPlot(); plot.setStartAngle(0); plot.setDirection(Rotation.ANTICLOCKWISE); ChartPanel panel = new ChartPanel(chart); getContentPane().add(panel, BorderLayout.CENTER); } 276 private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setLayout(new BorderLayout()); setTitle(“JFreePie Chart 2D”); setSize(400, 300); } Gráficos private PieDataset createDataSet() { DefaultPieDataset defaultDataSet = new DefaultPieDataset(); defaultDataSet.setValue(“Mozilla Firefox”, 40); defaultDataSet.setValue(“Google Chrome”, 25); defaultDataSet.setValue(“Internet Explorer”, 22); defaultDataSet.setValue(“Safari”, 8); defaultDataSet.setValue(“Opera”, 5); return defaultDataSet; } PR R O EP H I R BI O D D O U C IR } El resultado es el siguiente: Figura 72. Pie Chart 3D 12.4.2 Diagramas de líneas, área y barras JFreeChart permite la creación de diagrama de líneas (Line Chart), diagrama de área (Area Chart)y diagrama de barras (Bar Chart) en dos o tres dimensiones. En el momento de crear uno de estos chart es necesario asignar los datos mediante la clase DefaultCategoryDataSet en el método setValue. Este método permite incluir un valor que hará referencia a la elevación de la barra en el eje Y, un texto que indica una categoría y un texto que agrupa diferentes valores de categorías a un elemento que se visualiza en el eje X. 277 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández Ejemplo de Line Chart 2D package charts.line; import java.awt.BorderLayout; import java.io.File; import java.io.IOException; PR R O EP H I R BI O D D O U C IR import javax.swing.JFrame; import javax.swing.WindowConstants; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.CategoryDataset; import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.data.general.DefaultPieDataset; import org.jfree.data.general.PieDataset; public class FLine2D extends JFrame { public static void main(String[] args) { FLine2D frame = new FLine2D(); frame.setVisible(true); } public FLine2D() { initGUI(); CategoryDataset dataSet = new DefaultCategoryDataset(); dataSet = createDataSet(); JFreeChart chart = ChartFactory.createLineChart( ³&DOL¿FDFLRQHV´³(VWXGLDQWHV´³&DOL¿FDFLRQ´GDWD6HW PlotOrientation.VERTICAL, true, true, false); ChartPanel panel = new ChartPanel(chart); getContentPane().add(panel, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setLayout(new BorderLayout()); setTitle(“JFreeBar Chart 3D”); setSize(400, 300); } private CategoryDataset createDataSet() { DefaultCategoryDataset defaultDataSet = new DefaultCategoryDataset(); 278 Gráficos PR R O EP H I R BI O D D O U C IR defaultDataSet.setValue(4.5, “POO”, “Est1”); defaultDataSet.setValue(4.2, “Calculo”, “Est1”); defaultDataSet.setValue(3.0, “Fisica”, “Est1”); defaultDataSet.setValue(5.0, “POO”, “Est2”); defaultDataSet.setValue(3.5, “Calculo”, “Est2”); defaultDataSet.setValue(3.9, “Fisica”, “Est2”); defaultDataSet.setValue(2.0, “POO”, “Est3”); defaultDataSet.setValue(3.6, “Calculo”, “Est3”); defaultDataSet.setValue(4.8, “Fisica”, “Est3”); defaultDataSet.setValue(3.1, “POO”, “Est4”); defaultDataSet.setValue(2.5, “Calculo”, “Est4”); defaultDataSet.setValue(3.8, “Fisica”, “Est4”); return defaultDataSet; } } El resultado es el siguiente: Figura 73. Line Chart 2D Una aplicación interesante del Char Line y Bar Chart es que se puede ϐ ǡ mouse dicha área. En ese caso, si por ejemplo se selecciona el área ͵ͷǡǣ 279 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 74. Line Chart 2D Ampliado Ejemplo de Area Chart El siguiente código presenta un ejemplo de creación de un Area Chart2D con datos ingresados directamente en el código. En este chart se puede aplicar transparencias mediante el método setForegroundAlpha. La implementación es la siguiente: package charts.area; import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.WindowConstants; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.CategoryDataset; import org.jfree.data.category.DefaultCategoryDataset; public class FArea2D extends JFrame { 280 Gráficos public static void main(String[] args) { FArea2D frame = new FArea2D(); frame.setVisible(true); } PR R O EP H I R BI O D D O U C IR public FArea2D() { initGUI(); CategoryDataset dataSet = new DefaultCategoryDataset(); dataSet = createDataSet(); JFreeChart chart = ChartFactory.createAreaChart( ³&DOL¿FDFLRQHV´³(VWXGLDQWHV´³&DOL¿FDFLRQ´GDWD6HW PlotOrientation.VERTICAL, true, true, false); chart.getCategoryPlot().setForegroundAlpha(0.5f); ChartPanel panel = new ChartPanel(chart); getContentPane().add(panel, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setLayout(new BorderLayout()); setTitle(“JFreeChart Bar 3D”); setSize(400, 300); } private CategoryDataset createDataSet() { DefaultCategoryDataset defaultDataSet = new DefaultCategoryDataset(); defaultDataSet.setValue(4.5, “POO”, “Est1”); defaultDataSet.setValue(4.2, “Calculo”, “Est1”); defaultDataSet.setValue(3.0, “Fisica”, “Est1”); defaultDataSet.setValue(5.0, “POO”, “Est2”); defaultDataSet.setValue(3.5, “Calculo”, “Est2”); defaultDataSet.setValue(3.9, “Fisica”, “Est2”); defaultDataSet.setValue(2.0, “POO”, “Est3”); defaultDataSet.setValue(3.6, “Calculo”, “Est3”); defaultDataSet.setValue(4.8, “Fisica”, “Est3”); defaultDataSet.setValue(3.1, “POO”, “Est4”); defaultDataSet.setValue(2.5, “Calculo”, “Est4”); defaultDataSet.setValue(3.8, “Fisica”, “Est4”); return defaultDataSet; } } 281 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR El resultado es el siguiente: Figura 75. Area Chart 2D Ejemplo de Bar Chart 3D El siguiente código presenta un ejemplo de creación de un Bar Chart 3D con datos ingresados directamente en el código. La implementación es la siguiente: package charts.bar; import java.awt.BorderLayout; import java.io.File; import java.io.IOException; import javax.swing.JFrame; import javax.swing.WindowConstants; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.CategoryDataset; import org.jfree.data.category.DefaultCategoryDataset; 282 Gráficos import org.jfree.data.general.DefaultPieDataset; import org.jfree.data.general.PieDataset; public class FBar3D extends JFrame { public static void main(String[] args) { FBar3D frame = new FBar3D(); frame.setVisible(true); } PR R O EP H I R BI O D D O U C IR public FBar3D() { initGUI(); CategoryDataset dataSet = new DefaultCategoryDataset(); dataSet = createDataSet(); JFreeChart chart = ChartFactory.createBarChart3D( ³&DOL¿FDFLRQHV´³(VWXGLDQWHV´³&DOL¿FDFLRQ´GDWD6HW PlotOrientation.VERTICAL, true, true, false); ChartPanel panel = new ChartPanel(chart); getContentPane().add(panel, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setLayout(new BorderLayout()); setTitle(“JFreeBar Chart 3D”); setSize(400, 300); } private CategoryDataset createDataSet() { DefaultCategoryDataset defaultDataSet = new DefaultCategoryDataset(); defaultDataSet.setValue(4.5, “POO”, “Est1”); defaultDataSet.setValue(4.2, “Calculo”, “Est1”); defaultDataSet.setValue(3.0, “Fisica”, “Est1”); defaultDataSet.setValue(5.0, “POO”, “Est2”); defaultDataSet.setValue(3.5, “Calculo”, “Est2”); defaultDataSet.setValue(3.9, “Fisica”, “Est2”); defaultDataSet.setValue(2.0, “POO”, “Est3”); defaultDataSet.setValue(3.6, “Calculo”, “Est3”); defaultDataSet.setValue(4.8, “Fisica”, “Est3”); defaultDataSet.setValue(3.1, “POO”, “Est4”); defaultDataSet.setValue(2.5, “Calculo”, “Est4”); defaultDataSet.setValue(3.8, “Fisica”, “Est4”); return defaultDataSet; } } 283 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR El resultado es el siguiente: Figura 76. Bar Chart 3D 12.4.3 Histogramas JFreeChart permite la creación de histogramas. En el momento de crear uno de estos chart es necesario asignar los datos mediante la clase HistogramDataSet. Usando el método addSeries, el histograma recibe el nombre de la variable a medir los valores de la variable y la frecuencia. Ejemplo de Histograma El siguiente código presenta un ejemplo de creación de un histograma con datos aleatorios. La implementación es la siguiente: package charts.histogram; import java.awt.BorderLayout; import java.util.Random; import javax.swing.JFrame; import javax.swing.WindowConstants; 284 Gráficos import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.statistics.HistogramDataset; import org.jfree.data.statistics.HistogramType; public class FHistogram2D extends JFrame { PR R O EP H I R BI O D D O U C IR public static void main(String[] args) { FHistogram2D frame = new FHistogram2D(); frame.setVisible(true); } public FHistogram2D() { initGUI(); HistogramDataset dataSet = new HistogramDataset(); dataSet = createDataSet(); JFreeChart chart = ChartFactory.createHistogram( “Histograma”, “Valores”, “Frecuencia”, dataSet, PlotOrientation.VERTICAL, true, true, false); ChartPanel panel = new ChartPanel(chart); getContentPane().add(panel, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setLayout(new BorderLayout()); setTitle(“JFreeChart”); setSize(400, 300); } private HistogramDataset createDataSet() { HistogramDataset dataSet = new HistogramDataset(); Random random = new Random(); double []valores = new double[100]; for(int i=0; i<100; i++){ valores[i]=random.nextDouble()*100; } GDWD6HWVHW7\SH +LVWRJUDP7\SH5(/$7,9(B)5(48(1&< dataSet.addSeries(“Variable”, valores, 20); return dataSet; } } 285 Programación Orientada a Objetos usando Java Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR El resultado es el siguiente: Figura 77. Histograma 12.4.4 Diagramas polares JFreeChart permite la creación de diagramas polares. En el momento de crear uno de estos chart es necesario asignar los datos mediante la clase XYSeriesCollection, la cual permite agregar objetos de la clase XYSeries. La clase XTSeries recibe valores con base en el ángulo y el dato de la serie. Ejemplo de Polar Chart El siguiente código presenta un ejemplo de creación de un Polar Chart con datos aleatorios. La implementación es la siguiente: package charts.polar; import java.awt.BorderLayout; import java.util.Random; import javax.swing.JFrame; import javax.swing.WindowConstants; import org.jfree.chart.ChartFactory; 286 Gráficos import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; public class FPolar2D extends JFrame { PR R O EP H I R BI O D D O U C IR public static void main(String[] args) { FPolar2D frame = new FPolar2D(); frame.setVisible(true); } public FPolar2D() { initGUI(); XYDataset seriesCollection = new XYSeriesCollection(); seriesCollection = createSeriesCollection(); JFreeChart chart = ChartFactory.createPolarChart( “Polar”, seriesCollection, true, true, false); ChartPanel panel = new ChartPanel(chart); getContentPane().add(panel, BorderLayout.CENTER); } private void initGUI() { setDefaultCloseOperation( :LQGRZ&RQVWDQWV',6326(B21B&/26( setLayout(new BorderLayout()); setTitle(“JFreeChart”); setSize(400, 300); } private XYSeriesCollection createSeriesCollection() { XYSeriesCollection seriesCollection = new XYSeriesCollection(); XYSeries series; Random random = new Random(); for(int i=0; i<3; i++){ series = new XYSeries(“Serie “+ (i+1)); for(int j=0; j<4; j++){ int Angulo = j*90; int valor = (Math.abs(random.nextInt())%10)+1; series.add(Angulo, valor); } seriesCollection.addSeries(series); } return seriesCollection; } } El resultado es el siguiente: 287 Héctor Arturo Flórez Fernández PR R O EP H I R BI O D D O U C IR Programación Orientada a Objetos usando Java Figura 78. Polar Chart 12.5 Ejercicios propuestos 1. Implemente una aplicación que permita dibujar un círculo que posea movimiento con base en el teclado. El círculo debe iniciar en el centro de un área de dibujo (JPanel). Si el usuario presiona la tecla “ϔ ” el círculo se ͳͲÀ Ǥ tecla “ϔ dz À ͳͲÀ izquierda. Si el usuario presiona la tecla “ϔ ” el À ͳͲÀǤ la tecla “ϔ dz À ͳͲÀǤ 2. Implemente una aplicación que permita dibujar un círculo que persiga el puntero del mouse. Esto indica que si el usuario mueve el puntero del mouse en el área de dibujo (JPanel), el círculo se repinta teniendo como centro las coordenadas del mouse. 3. Realice un histograma que contenga los valores del TRM del dólar del último año. 288