Tutorial Java Ya 3

246
41. Estructuras dinámicas: Listas Una lista es un conjunto de nodos, cada uno de los cuales tiene dos campos: uno de información y un apuntador al siguiente nodo de la lista. Además un apuntador externo señala el primer nodo de la lista. Representación gráfica de un nodo: La información puede ser cualquier tipo de dato simple, estructura de datos o inclusive uno o más objetos. La dirección al siguiente nodo es un puntero. Representación gráfica de una lista: Como decíamos, una lista es una secuencia de nodos (en este caso cuatro nodos). La información de los nodos en este caso es un entero y siempre contiene un puntero que guarda la dirección del siguiente nodo. raiz es otro puntero externo a la lista que contiene la dirección del primer nodo. El estado de una lista varía durante la ejecución del programa: De esta forma representamos gráficamente una lista vacía. Si insertamos un nodo en la lista quedaría luego: Si insertamos otro nodo al principio con el valor 9 tenemos:

Transcript of Tutorial Java Ya 3

Page 1: Tutorial Java Ya 3

41. Estructuras dinámicas: Listas

Una lista es un conjunto de nodos, cada uno de los cuales tiene dos campos: uno de información y un apuntador al siguiente nodo de la lista. Además un apuntador externo señala el primer nodo de la lista.Representación gráfica de un nodo:

La información puede ser cualquier tipo de dato simple, estructura de datos o inclusive uno o más objetos.La dirección al siguiente nodo es un puntero.Representación gráfica de una lista:

Como decíamos, una lista es una secuencia de nodos (en este caso cuatro nodos). La información de los nodos en este caso es un entero y siempre contiene un puntero que guarda la dirección del siguiente nodo.raiz es otro puntero externo a la lista que contiene la dirección del primer nodo.El estado de una lista varía durante la ejecución del programa:

De esta forma representamos gráficamente una lista vacía. Si insertamos un nodo en la lista quedaría luego:

Si insertamos otro nodo al principio con el valor 9 tenemos:

Lo mismo podemos borrar nodos de cualquier parte de la lista.Esto nos trae a la mente el primer problema planteado: el desarrollo del procesador de texto. Podríamos utilizar una lista que inicialmente estuviera vacía e introdujéramos un nuevo nodo con cada línea que tipea el operador. Con esta estructura haremos un uso muy eficiente de la memoria.

Page 2: Tutorial Java Ya 3

Tipos de listas.

Según el mecanismo de inserción y extracción de nodos en la lista tenemos los siguientes tipos:

Listas tipo pila. Listas tipo cola. Listas genéricas.

Una lista se comporta como una pila si las inserciones y extracciones las hacemos por un mismo lado de la lista. También se las llama listas LIFO (Last In First Out - último en entrar primero en salir)Una lista se comporta como una cola si las inserciones las hacemos al final y las extracciones las hacemos por el frente de la lista. También se las llama listas FIFO (First In First Out - primero en entrar primero en salir)Una lista se comporta como genérica cuando las inserciones y extracciones se realizan en cualquier parte de la lista.Podemos en algún momento insertar un nodo en medio de la lista, en otro momento al final, borrar uno del frente, borrar uno del fondo o uno interior, etc.

42. Estructuras dinámicas: Listas tipo Pila

Una lista se comporta como una pila si las inserciones y extracciones las hacemos por un mismo lado de la lista. También se las llama listas LIFO (Last In First Out - último en entrar primero en salir)

Importante: Una pila al ser una lista puede almacenar en el campo de información cualquier tipo de valor (int, char, float, vector de caracteres, un objeto, etc)Para estudiar el mecanismo de utilización de una pila supondremos que en el campo de información almacena un entero (para una fácil interpretación y codificación)Inicialmente la PILA está vacía y decimos que el puntero raiz apunta a null (Si apunta a null decimos que no tiene una dirección de memoria):

Insertamos un valor entero en la pila: insertar(10)

Luego de realizar la inserción la lista tipo pila queda de esta manera: un nodo con el valor 10 y raiz apunta a dicho nodo. El puntero del nodo apunta a null ya que no hay otro nodo después de este.Insertamos luego el valor 4: insertar(4)

Page 3: Tutorial Java Ya 3

Ahora el primer nodo de la pila es el que almacena el valor cuatro. raiz apunta a dicho nodo. Recordemos que raiz es el puntero externo a la lista que almacena la dirección del primer nodo. El nodo que acabamos de insertar en el campo puntero guarda la dirección del nodo que almacena el valor 10.

Ahora qué sucede si extraemos un nodo de la pila. ¿Cuál se extrae? Como sabemos en una pila se extrae el último en entrar.Al extraer de la pila tenemos: extraer()

La pila ha quedado con un nodo.Hay que tener cuidado que si se extrae un nuevo nodo la pila quedará vacía y no se podrá extraer otros valores (avisar que la pila está vacía)

Problema 1:

Confeccionar una clase que administre una lista tipo pila (se debe poder insertar, extraer e imprimir los datos de la pila)

Programa:

public class Pila {

class Nodo { int info; Nodo sig; }

private Nodo raiz; public Pila () { raiz=null; } public void insertar(int x) { Nodo nuevo; nuevo = new Nodo(); nuevo.info = x;

Page 4: Tutorial Java Ya 3

if (raiz==null) { nuevo.sig = null; raiz = nuevo; } else { nuevo.sig = raiz; raiz = nuevo; } } public int extraer () { if (raiz!=null) { int informacion = raiz.info; raiz = raiz.sig; return informacion; } else { return Integer.MAX_VALUE; } } public void imprimir() { Nodo reco=raiz; System.out.println("Listado de todos los elementos de la pila."); while (reco!=null) { System.out.print(reco.info+"-"); reco=reco.sig; } System.out.println(); } public static void main(String[] ar) { Pila pila1=new Pila(); pila1.insertar(10); pila1.insertar(40); pila1.insertar(3);

Page 5: Tutorial Java Ya 3

pila1.imprimir(); System.out.println("Extraemos de la pila:"+pila1.extraer()); pila1.imprimir(); }}

Analicemos las distintas partes de este programa: class Nodo { int info; Nodo sig; }

private Nodo raiz;

Para declarar un nodo debemos utilizar una clase. En este caso la información del nodo (info) es un entero y siempre el nodo tendrá una referencia de tipo Nodo, que le llamamos sig.

El puntero sig apunta al siguiente nodo o a null en caso que no exista otro nodo. Este puntero es interno a la lista.

También definimos un puntero de tipo Nodo llamado raiz. Este puntero tiene la dirección del primer nodo de la lista. En caso de estar vacía la lista, raiz apunta a null (es decir no tiene dirección)

El puntero raiz es fundamental porque al tener la dirección del primer nodo de la lista nos permite acceder a los demás nodos. public Pila () { raiz=null; }

En el constructor de la clase hacemos que raiz guarde el valor null. Tengamos en cuenta que si raiz tiene almacenado null la lista está vacía, en caso contrario tiene la dirección del primer nodo de la lista. public void insertar(int x) { Nodo nuevo; nuevo = new Nodo(); nuevo.info = x; if (raiz==null) { nuevo.sig = null; raiz = nuevo; } else { nuevo.sig = raiz; raiz = nuevo; }

Page 6: Tutorial Java Ya 3

}

Uno de los métodos más importantes que debemos entender en una pila es el de insertar un elemento en la pila.

Al método llega la información a insertar, en este caso en particular es un valor entero.

La creación de un nodo requiere dos pasos:- Definición de un puntero o referencia a un tipo de dato Nodo: Nodo nuevo;

- Creación del nodo (creación de un objeto):

nuevo = new Nodo();Cuando se ejecuta el operador new se reserva espacio para el nodo. Realmente se crea el nodo cuando se ejecuta el new.

Paso seguido debemos guardar la información del nodo: nuevo.info = x;

En el campo info almacenamos lo que llega en el parámetro x. Por ejemplo si llega un 5 el nodo queda:

Por último queda enlazar el nodo que acabamos de crear al principio de la lista.Si la lista está vacía debemos guardar en el campo sig del nodo el valor null para indicar que no hay otro nodo después de este, y hacer que raiz apunte al nodo creado (sabemos si una lista esta vacía si raiz almacena un null) if (raiz==null) { nuevo.sig = null; raiz = nuevo; }

Gráficamente podemos observar que cuando indicamos raiz=nuevo, el puntero raiz guarda la dirección del nodo apuntado por nuevo.Tener en cuenta que cuando finaliza la ejecución del método el puntero nuevo desaparece, pero no el nodo creado con el operador new.

Page 7: Tutorial Java Ya 3

En caso que la lista no esté vacía, el puntero sig del nodo que acabamos de crear debe apuntar al que es hasta este momento el primer nodo, es decir al nodo que apunta raiz actualmente. else { nuevo.sig = raiz; raiz = nuevo; }

Como primera actividad cargamos en el puntero sig del nodo apuntado por nuevo la dirección de raiz, y posteriormente raiz apunta al nodo que acabamos de crear, que será ahora el primero de la lista.Antes de los enlaces tenemos:

Luego de ejecutar la línea: nuevo.sig = raiz;

Ahora tenemos:

Por último asignamos a raiz la dirección que almacena el puntero nuevo. raiz = nuevo;

La lista queda:

El método extraer: public int extraer () { if (raiz!=null) { int informacion = raiz.info; raiz = raiz.sig; return informacion; } else { return Integer.MAX_VALUE; }

Page 8: Tutorial Java Ya 3

}El objetivo del método extraer es retornar la información del primer nodo y además borrarlo de la lista.

Si la lista no está vacía guardamos en una variable local la información del primer nodo: int informacion = raiz.info;

Avanzamos raiz al segundo nodo de la lista, ya que borraremos el primero: raiz = raiz.sig;

el nodo que previamente estaba apuntado por raiz es eliminado automáticamente por la máquina virtual de Java, al no tener ninguna referencia.

Retornamos la información: return informacion;

En caso de estar vacía la pila retornamos el número entero máximo y lo tomamos como código de error (es decir nunca debemos guardar el entero mayor en la pila) return Integer.MAX_VALUE;

Es muy importante entender gráficamente el manejo de las listas. La interpretación gráfica nos permitirá plantear inicialmente las soluciones para el manejo de listas.

Por último expliquemos el método para recorrer una lista en forma completa e imprimir la información de cada nodo: public void imprimir() { Nodo reco=raiz; System.out.println("Listado de todos los elementos de la pila."); while (reco!=null) {

Page 9: Tutorial Java Ya 3

System.out.print(reco.info+"-"); reco=reco.sig; } System.out.println(); }

Definimos un puntero auxiliar reco y hacemos que apunte al primer nodo de la lista: Nodo reco=raiz;

Disponemos una estructura repetitiva que se repetirá mientras reco sea distinto a null. Dentro de la estructura repetitiva hacemos que reco avance al siguiente nodo: while (reco!=null) { System.out.print(reco.info+"-"); reco=reco.sig; }

Es muy importante entender la línea: reco=reco.sig;

Estamos diciendo que reco almacena la dirección que tiene el puntero sig del nodo apuntado actualmente por reco.

Gráficamente:

Al analizarse la condición: while (reco!=null) {

se valúa en verdadero ya que reco apunta a un nodo y se vuelve a ejecutar la línea: reco=reco.sig;

Ahora reco apunta al siguiente nodo:

Page 10: Tutorial Java Ya 3

La condición del while nuevamente se valúa en verdadera y avanza el puntero reco al siguiente nodo: reco=reco.sig;

Ahora sí reco apunta a null y ha llegado el final de la lista (Recordar que el último nodo de la lista tiene almacenado en el puntero sig el valor null, con el objetivo de saber que es el último nodo)Para poder probar esta clase recordemos que debemos definir un objeto de la misma y llamar a sus métodos: public static void main(String[] ar) { Pila pila1=new Pila(); pila1.insertar(10); pila1.insertar(40); pila1.insertar(3); pila1.imprimir(); System.out.println("Extraemos de la pila:"+pila1.extraer()); pila1.imprimir(); }

Insertamos 3 enteros, luego imprimimos la pila, extraemos uno de la pila y finalmente imprimimos nuevamente la pila.

Problema 2:

Agregar a la clase Pila un método que retorne la cantidad de nodos y otro que indique si esta vacía.

Programa:

public class Pila {

class Nodo { int info; Nodo sig;}

private Nodo raiz;

Page 11: Tutorial Java Ya 3

Pila () { raiz=null; } public void insertar(int x) { Nodo nuevo; nuevo = new Nodo(); nuevo.info = x; if (raiz==null) { nuevo.sig = null; raiz = nuevo; } else { nuevo.sig = raiz; raiz = nuevo; } } public int extraer () { if (raiz!=null) { int informacion = raiz.info; raiz = raiz.sig; return informacion; } else { return Integer.MAX_VALUE; } } public void imprimir() { Nodo reco=raiz; System.out.println("Listado de todos los elementos de la pila."); while (reco!=null) { System.out.print(reco.info+"-"); reco=reco.sig;

Page 12: Tutorial Java Ya 3

} System.out.println(); } public boolean vacia() { if (raiz==null) { return true; } else { return false; } } public int cantidad() { int cant=0; Nodo reco=raiz; while (reco!=null) { cant++; reco=reco.sig; } return cant; } public static void main(String[] ar) { Pila pila1=new Pila(); pila1.insertar(10); pila1.insertar(40); pila1.insertar(3); pila1.imprimir(); System.out.println("La cantidad de nodos de la lista es:"+pila1.cantidad()); while (pila1.vacia()==false) { System.out.println(pila1.extraer()); } }}

Para verificar si la pila esta vacía verificamos el contenido de la variable raiz, si tiene null luego la lista esta vacía y por lo tanto retornamos un true: public boolean vacia() { if (raiz==null) { return true; } else { return false;

Page 13: Tutorial Java Ya 3

} }

El algoritmo para saber la cantidad de nodos es similar al imprimir, pero en lugar de mostrar la información del nodo procedemos a incrementar un contador: public int cantidad() { int cant=0; Nodo reco=raiz; while (reco!=null) { cant++; reco=reco.sig; } return cant; }

Para probar esta clase en la main creamos un objeto de la clase Pila insertamos tres enteros: Pila pila1=new Pila(); pila1.insertar(10); pila1.insertar(40); pila1.insertar(3);

Imprimimos la pila (nos muestra los tres datos): pila1.imprimir();

Llamamos al método cantidad (nos retorna un 3): System.out.println("La cantidad de nodos de la lista es:"+pila1.cantidad());

Luego mientras el método vacía nos retorne un false (lista no vacía) procedemos a llamar al método extraer: while (pila1.vacia()==false) { System.out.println(pila1.extraer()); }

Problemas propuestos

1. Agregar un método a la clase Pila que retorne la información del primer nodo de la Pila sin borrarlo.

Solución

public class Pila {

class Nodo { int info; Nodo sig;}

private Nodo raiz; Pila () { raiz=null;

Page 14: Tutorial Java Ya 3

} public void insertar(int x) { Nodo nuevo; nuevo = new Nodo(); nuevo.info = x; if (raiz==null) { nuevo.sig = null; raiz = nuevo; } else { nuevo.sig = raiz; raiz = nuevo; } } public int extraer () { if (raiz!=null) { int informacion = raiz.info; raiz = raiz.sig; return informacion; } else { return Integer.MAX_VALUE; } } public int retornar () { if (raiz!=null) { int informacion = raiz.info; return informacion; } else { return Integer.MAX_VALUE; } } public void imprimir() { Nodo reco=raiz; System.out.println("Listado de todos los elementos de la pila."); while (reco!=null) {

Page 15: Tutorial Java Ya 3

System.out.print(reco.info+"-"); reco=reco.sig; } System.out.println(); } public static void main(String[] ar) { Pila pila1=new Pila(); pila1.insertar(10); pila1.insertar(40); pila1.insertar(3); pila1.imprimir(); System.out.println("Extraemos de la pila:"+pila1.extraer()); pila1.imprimir(); System.out.println("Retornamos primero de la pila:"+pila1.retornar()); pila1.imprimir(); }}

43. Estructuras dinámicas: Listas tipo Pila - Problema de aplicación

Hasta ahora hemos visto como desarrollar los algoritmos para administrar una lista tipo Pila, hemos visto que hay bastante complejidad en el manejo de punteros pero todo esto acarrea ventajas en la solución de problemas que requieren una estructura de tipo Pila.

Planteo del problema:Este práctico tiene por objetivo mostrar la importancia de las pilas en las Ciencias de la Computación y más precisamente en la programación de software de bajo nivel.Todo compilador o intérprete de un lenguaje tiene un módulo dedicado a analizar si una expresión está correctamente codificada, es decir que los paréntesis estén abiertos y cerrados en un orden lógico y bien balanceados.

Se debe desarrollar una clase que tenga las siguientes responsabilidades (clase Formula):- Ingresar una fórmula que contenga paréntesis, corchetes y llaves.- Validar que los ( ) [] y {} estén correctamente balanceados.

Para la solución de este problema la clase formula tendrá un atributo de la clase Pila.

Veamos como nos puede ayudar el empleo de una pila para solucionar este problema.

Primero cargaremos la fórmula en un JTextField.

Ejemplo de fórmula: (2+[3-12]*{8/3})

El algoritmo de validación es el siguiente:

Page 16: Tutorial Java Ya 3

Analizamos caracter a caracter la presencia de los paréntesis, corchetes y llaves.

Si vienen símbolos de apertura los almacenamos en la pila.

Si vienen símbolos de cerrado extraemos de la pila y verificamos si está el mismo símbolo pero de apertura: en caso negativo podemos inferir que la fórmula no está correctamente balanceada.Si al finalizar el análisis del último caracter de la fórmula la pila está vacía podemos concluir que está correctamente balanceada.

Ejemplos de fórmulas no balanceadas:}(2+[3-12]*{8/3})Incorrecta: llega una } de cerrado y la pila está vacía.{[2+4}]Incorrecta: llega una llave } y en el tope de la pila hay un corchete [.{[2+4]Incorrecta: al finalizar el análisis del último caracter en la pila queda pendiente una llave {.

Programa:

public class Pila {

class Nodo { char simbolo; Nodo sig;}

private Nodo raiz; Pila () { raiz=null; } public void insertar(char x) { Nodo nuevo; nuevo = new Nodo(); nuevo.simbolo = x; if (raiz==null)

Page 17: Tutorial Java Ya 3

{ nuevo.sig = null; raiz = nuevo; } else { nuevo.sig = raiz; raiz = nuevo; } } public char extraer () { if (raiz!=null) { char informacion = raiz.simbolo; raiz = raiz.sig; return informacion; } else { return Character.MAX_VALUE; } } public boolean vacia() { if (raiz==null) { return true; } else { return false; } }}

import javax.swing.*;import java.awt.event.*;public class Formula extends JFrame implements ActionListener { private JTextField tf1; private JButton boton1; public Formula() { setLayout(null);

Page 18: Tutorial Java Ya 3

tf1=new JTextField("{2*(4-5)-{3*4}-[4-5]}"); tf1.setBounds(10,10,230,30); add(tf1); boton1=new JButton("Verificar fórmula."); boton1.setBounds(10,70,180,30); add(boton1); boton1.addActionListener(this); } public void actionPerformed(ActionEvent e) { if (e.getSource()==boton1) { if (balanceada()) { setTitle("Está correctamente balanceada."); } else { setTitle("No está correctamente balanceada."); } } }

public boolean balanceada() { Pila pila1; pila1 = new Pila (); String cadena=tf1.getText(); for (int f = 0 ; f < cadena.length() ; f++) { if (cadena.charAt(f) == '(' || cadena.charAt(f) == '[' || cadena.charAt(f) == '{') { pila1.insertar(cadena.charAt(f)); } else { if (cadena.charAt(f)==')') { if (pila1.extraer()!='(') { return false; } } else { if (cadena.charAt(f)==']') { if (pila1.extraer()!='[') { return false; } } else { if (cadena.charAt(f)=='}') { if (pila1.extraer()!='{') {

Page 19: Tutorial Java Ya 3

return false; } } } } } } if (pila1.vacia()) { return true; } else { return false; } } public static void main(String[] ar) { Formula formula1=new Formula(); formula1.setBounds(0,0,350,140); formula1.setVisible(true); } }

Primero declaramos y definimos la clase Pila. Almacenamos en cada nodo un caracter y llamamos al campo de información símbolo.

No es necesario implementar los métodos imprimir, cantidad, etc. Porque no se requieren para este problema.

La clase Formula tiene como atributos: private JTextField tf1; private JButton boton1;

En el constructor creamos los dos objetos y los ubicamos: setLayout(null); tf1=new JTextField("{2*(4-5)-{3*4}-[4-5]}"); tf1.setBounds(10,10,230,30); add(tf1); boton1=new JButton("Verificar fórmula."); boton1.setBounds(10,70,180,30); add(boton1); boton1.addActionListener(this);

En el método actionPerformed llamamos al método balanceada que debe retornar si la fórmula están correctos los parentesis, corchetes y llaves: if (e.getSource()==boton1) {

Page 20: Tutorial Java Ya 3

if (balanceada()) { setTitle("Está correctamente balanceada."); } else { setTitle("No está correctamente balanceada."); } }

El método más importante es el balanceada.En este analizamos la fórmula para verificar si está correctamente balanceada.En este método es donde está gran parte del algoritmo de este problema. Retorna true en caso de ser correcta y false en caso contrario.

Definimos una pila y extraemos el contenido del JTextField: Pila pila1; pila1 = new Pila (); String cadena=tf1.getText();

El for se repite tantas veces como caracteres tenga el JTextField.Se deben procesar sólo los símbolos ( [ { y ) ] }.Si el símbolo es un ( [ { de apertura procedemos a cargarlo en la pila: if (cadena.charAt(f) == '(' || cadena.charAt(f) == '[' || cadena.charAt(f) == '{') { pila1.insertar(cadena.charAt(f));

En caso de ser un ) cerrado debemos extraer un carácter de la pila y verificar si no coincide con el paréntesis de apertura ( la fórmula está incorrecta: if (cadena.charAt(f)==')') { if (pila1.extraer()!='(') { return false; }

El mismo proceso es para los símbolos ] }.

Al finalizar el análisis de toda la cadena si la pila está vacía podemos afirmar que la fórmula está correctamente balanceada, en caso contrario quiere decir que faltan símbolos de cerrado y es incorrecta: if (pila1.vacia()) { return true; } else { return false; }

Es importante entender que la clase Formula utiliza un objeto de la clase Pila para resolver el algoritmo de verificar el balanceo de la fórmula, pero no accede directamente a los nodos de la lista.

44. Estructuras dinámicas: Listas tipo Cola

Una lista se comporta como una cola si las inserciones las hacemos al final y las extracciones las hacemos por el frente de la lista. También se las llama listas FIFO (First In First Out - primero en entrar primero en salir)

Page 21: Tutorial Java Ya 3

Confeccionaremos un programa que permita administrar una lista tipo cola. Desarrollaremos los métodos de insertar, extraer, vacia e imprimir.

Programa:

public class Cola { class Nodo { int info; Nodo sig; } private Nodo raiz,fondo; Cola() { raiz=null; fondo=null; } boolean vacia (){ if (raiz == null) return true; else return false; }

void insertar (int info) { Nodo nuevo; nuevo = new Nodo (); nuevo.info = info; nuevo.sig = null; if (vacia ()) { raiz = nuevo; fondo = nuevo; } else { fondo.sig = nuevo; fondo = nuevo; } }

int extraer () { if (!vacia ())

Page 22: Tutorial Java Ya 3

{ int informacion = raiz.info; if (raiz == fondo){ raiz = null; fondo = null; } else { raiz = raiz.sig; } return informacion; } else return Integer.MAX_VALUE; }

public void imprimir() { Nodo reco=raiz; System.out.println("Listado de todos los elementos de la cola."); while (reco!=null) { System.out.print(reco.info+"-"); reco=reco.sig; } System.out.println(); } public static void main(String[] ar) { Cola cola1=new Cola(); cola1.insertar(5); cola1.insertar(10); cola1.insertar(50); cola1.imprimir(); System.out.println("Extraemos uno de la cola:"+cola1.extraer()); cola1.imprimir(); }}

La declaración del nodo es igual a la clase Pila. Luego definimos dos punteros externos: private Nodo raiz,fondo;

raíz apunta al principio de la lista y fondo al final de la lista. Utilizar dos punteros tiene como ventaja que cada vez que tengamos que insertar un nodo al final de la lista no tengamos que recorrerla. Por supuesto que es perfectamente válido implementar una cola con un único puntero externo a la lista.

Page 23: Tutorial Java Ya 3

En el constructor inicializamos a los dos punteros en null (Realmente esto es opcional ya que los atributos de una clase en java se inicializan automáticamente con null): Cola() { raiz=null; fondo=null; }

El método vacía retorna true si la lista no tiene nodos y false en caso contrario: boolean vacia (){ if (raiz == null) return true; else return false; }

En la inserción luego de crear el nodo tenemos dos posibilidades: que la cola esté vacía, en cuyo caso los dos punteros externos a la lista deben apuntar al nodo creado, o que haya nodos en la lista. Nodo nuevo; nuevo = new Nodo (); nuevo.info = info; nuevo.sig = null; if (vacia ()) { raiz = nuevo; fondo = nuevo; } else { fondo.sig = nuevo; fondo = nuevo; }

Recordemos que definimos un puntero llamado nuevo, luego creamos el nodo con el operador new y cargamos los dos campos, el de información con lo que llega en el parámetro y el puntero con null ya que se insertará al final de la lista, es decir no hay otro después de este.Si la lista está vacía:

En caso de no estar vacía:

Page 24: Tutorial Java Ya 3

Debemos enlazar el puntero sig del último nodo con el nodo recién creado: fondo.sig = nuevo;

Y por último el puntero externo fondo debe apuntar al nodo apuntado por nuevo: fondo = nuevo;

Con esto ya tenemos correctamente enlazados los nodos en la lista tipo cola. Recordar que el puntero nuevo desaparece cuando se sale del método insertar, pero el nodo creado no se pierde porque queda enlazado en la lista.

El funcionamiento del método extraer es similar al de la pila: int extraer () { if (!vacia ()) { int informacion = raiz.info; if (raiz == fondo){ raiz = null; fondo = null; } else { raiz = raiz.sig; } return informacion; } else return Integer.MAX_VALUE; }

Si la lista no está vacía guardamos en una variable local la información del primer nodo: int informacion = raiz.info;

Para saber si hay un solo nodo verificamos si los dos punteros raiz y fondo apuntan a la misma dirección de memoria: if (raiz == fondo){

Page 25: Tutorial Java Ya 3

Luego hacemos: raiz = null; fondo = null;

En caso de haber 2 o más nodos debemos avanzar el puntero raiz al siguiente nodo:

raiz = raiz.sig;

Ya tenemos la lista correctamente enlazada (raiz apunta al primer nodo y fondo continúa apuntando al último nodo)

45. Estructuras dinámicas: Listas tipo Cola - Problemas de aplicación

Planteo del problema:Este práctico tiene por objetivo mostrar la importancia de las colas en las Ciencias de la Computación y más precisamente en las simulaciones.Las simulaciones permiten analizar situaciones de la realidad sin la necesidad de ejecutarlas realmente. Tiene el beneficio que su costo es muy inferior a hacer pruebas en la realidad.Desarrollar un programa para la simulación de un cajero automático.

Se cuenta con la siguiente información:- Llegan clientes a la puerta del cajero cada 2 ó 3 minutos.- Cada cliente tarda entre 2 y 4 minutos para ser atendido.

Page 26: Tutorial Java Ya 3

Obtener la siguiente información:1 - Cantidad de clientes que se atienden en 10 horas.2 - Cantidad de clientes que hay en cola después de 10 horas.3 - Hora de llegada del primer cliente que no es atendido luego de 10 horas (es decir la persona que está primera en la cola cuando se cumplen 10 horas)

Programa:

public class Cola { class Nodo { int info; Nodo sig; } Nodo raiz,fondo; Cola() { raiz=null; fondo=null; } boolean vacia (){ if (raiz == null) return true; else return false; }

void insertar (int info) { Nodo nuevo; nuevo = new Nodo (); nuevo.info = info; nuevo.sig = null; if (vacia ()) { raiz = nuevo; fondo = nuevo; } else { fondo.sig = nuevo; fondo = nuevo; } }

Page 27: Tutorial Java Ya 3

int extraer () { if (!vacia ()) { int informacion = raiz.info; if (raiz == fondo){ raiz = null; fondo = null; } else { raiz = raiz.sig; } return informacion; } else return Integer.MAX_VALUE; }

public void imprimir() { Nodo reco=raiz; System.out.println("Listado de todos los elementos de la cola."); while (reco!=null) { System.out.print(reco.info+"-"); reco=reco.sig; } System.out.println(); } public int cantidad() { int cant=0; Nodo reco=raiz; while (reco!=null) { cant++; reco=reco.sig; } return cant; } }

Page 28: Tutorial Java Ya 3

import javax.swing.*;import java.awt.event.*;public class Cajero extends JFrame implements ActionListener{ private JLabel l1,l2,l3; private JButton boton1; public Cajero() { setLayout(null); boton1=new JButton("Activar Simulación"); boton1.setBounds(10,10,180,30); add(boton1); boton1.addActionListener(this); l1=new JLabel("Atendidos:"); l1.setBounds(10,50,300,30); add(l1); l2=new JLabel("En cola:"); l2.setBounds(10,90,300,30); add(l2); l3=new JLabel("Minuto de llegada:"); l3.setBounds(10,130,400,30); add(l3); } public void actionPerformed(ActionEvent e) { if (e.getSource()==boton1) { simulacion(); } }

public void simulacion () { int estado = 0; int llegada = 2 + (int) (Math.random () * 2); int salida = -1; int cantAtendidas = 0; Cola cola = new Cola (); for (int minuto = 0 ; minuto < 600 ; minuto++) { if (llegada == minuto) { if (estado==0) { estado=1; salida=minuto+2+(int)(Math.random()*3);

Page 29: Tutorial Java Ya 3

} else { cola.insertar(minuto); } llegada=minuto+2+(int)(Math.random()*2); } if (salida == minuto) { estado=0; cantAtendidas++; if (!cola.vacia()) { cola.extraer(); estado=1; salida=minuto+2+(int)(Math.random()*3); } } } l1.setText("Atendidos:"+String.valueOf(cantAtendidas)); l2.setText("En cola"+String.valueOf(cola.cantidad())); l3.setText("Minuto llegada:"+String.valueOf(cola.extraer())); } public static void main(String[] ar) { Cajero cajero1=new Cajero(); cajero1.setBounds(0,0,340,250); cajero1.setVisible(true); } }

La clase Cola colabora con la clase Cajero. En la clase cola debemos definir como mínimo los métodos de insertar, extraer, vacía y cantidad.La clase Cajero define tres objetos de la clase JLabel para mostrar los resultados de la simulación.

El método más importante es el de simulacion, veamos las distintas partes de dicho método: int estado = 0; int llegada = 2 + (int) (Math.random () * 2); int salida = -1; int cantAtendidas = 0; Cola cola = new Cola ();

Page 30: Tutorial Java Ya 3

La variable estado almacena un cero si el cajero está libre y un uno cuando está ocupado.La variable llegada almacena en que minuto llegará el próximo cliente (debemos generar un valor entre 2 y 3)

La variable salida almacenará en que minuto terminará el cliente de ser atendido (como al principio el cajero está vacío inicializamos esta variable con -1.Llevamos un contador para saber la cantidad de personas atendidas (cantAtendidas)Luego definimos un objeto de la clase Cola para poder almacenar las personas que llegan al cajero y se lo encuentran ocupado.

Disponemos un for que se repita 600 veces (600 minutos o lo que es lo mismo 10 horas) for (int minuto = 0 ; minuto < 600 ; minuto++) {

Dentro del for hay dos if fundamentales que verifican que sucede cuando llega una persona o cuando una persona se retira: if (llegada == minuto) { ............ } if (salida == minuto) { ............ }

Cuando llega una persona al cajero primero verificamos si el cajero está desocupado: if (llegada == minuto) { if (estado==0) {

Si está desocupado lo ocupamos cambiando el valor de la variable estado y generando en que minuto esta persona dejará el cajero (un valor aleatorio entre 2 y 4 minutos): estado=1; salida=minuto+2+(int)(Math.random()*3);

Si el cajero está ocupado procedemos a cargar dicha persona en la cola (insertamos el minuto que llega): } else { cola.insertar(minuto); }

Luego generamos el próximo minuto que llegará otra persona: llegada=minuto+2+(int)(Math.random()*2);

El otro if importante es ver que sucede cuando sale la persona del cajero:if (salida == minuto) {

Si sale una persona del cajero cambiamos el valor de la variable estado, incrementamos en uno el contador cantAtendidos y si la cola no está vacía extraemos una persona, cambiamos a uno la variable estado y generamos en que minuto dejará esta persona el cajero: estado=0; cantAtendidas++; if (!cola.vacia()) { cola.extraer(); estado=1;

Page 31: Tutorial Java Ya 3

salida=minuto+2+(int)(Math.random()*3); } }

Fuera del for actualizamos las tres JLabel: l1.setText("Atendidos:"+String.valueOf(cantAtendidas)); l2.setText("En cola"+String.valueOf(cola.cantidad())); l3.setText("Minuto llegada:"+String.valueOf(cola.extraer()));

Problemas propuestos1. Un supermercado tiene tres cajas para la atención de los clientes.

Las cajeras tardan entre 7 y 11 minutos para la atención de cada cliente.Los clientes llegan a la zona de cajas cada 2 ó 3 minutos. (Cuando el cliente llega, si todas las cajas tienen 6 personas, el cliente se marcha del supermercado)Cuando el cliente llega a la zona de cajas elige la caja con una cola menor.Realizar una simulación durante 8 horas y obtener la siguiente información:a - Cantidad de clientes atendidos por cada caja.b - Cantidad de clientes que se marcharon sin hacer compras.c - Tiempo promedio en cola.

Solución

public class Cola { class Nodo { int info; Nodo sig; } Nodo raiz,fondo; Cola() { raiz=null; fondo=null; } boolean vacia (){ if (raiz == null) return true; else return false; }

void insertar (int info) { Nodo nuevo; nuevo = new Nodo (); nuevo.info = info; nuevo.sig = null; if (vacia ()) { raiz = nuevo; fondo = nuevo;

Page 32: Tutorial Java Ya 3

} else { fondo.sig = nuevo; fondo = nuevo; } }

int extraer () { if (!vacia ()) { int informacion = raiz.info; if (raiz == fondo){ raiz = null; fondo = null; } else { raiz = raiz.sig; } return informacion; } else return Integer.MAX_VALUE; }

public void imprimir() { Nodo reco=raiz; System.out.println("Listado de todos los elementos de la cola."); while (reco!=null) { System.out.print(reco.info+"-"); reco=reco.sig; } System.out.println(); } public int cantidad() { int cant=0; Nodo reco=raiz; while (reco!=null) { cant++; reco=reco.sig; } return cant; } }

import javax.swing.*;

Page 33: Tutorial Java Ya 3

import java.awt.event.*;public class Supermercado extends JFrame implements ActionListener { private JButton boton1; private JLabel l1,l2,l3; public Supermercado() { setLayout(null); boton1=new JButton("Activar Simulación"); boton1.setBounds(10,10,180,30); add(boton1); boton1.addActionListener(this); l1=new JLabel("Clientes atendidos por caja:"); l1.setBounds(10,50,400,30); add(l1); l2=new JLabel("Se marchan sin hacer compras:"); l2.setBounds(10,90,400,30); add(l2); l3=new JLabel("Tiempo promedio en cola:"); l3.setBounds(10,130,400,30); add(l3); } public void actionPerformed(ActionEvent e) { if (e.getSource()==boton1) { simulacion(); } }

public void simulacion () { int estado1=0,estado2=0,estado3=0; int marchan=0; int llegada = 2 + (int) (Math.random () * 2); int salida1=-1,salida2=-1,salida3=-1; int cantAte1=0,cantAte2=0,cantAte3=0; int tiempoEnCola=0; int cantidadEnCola=0; Cola cola1 = new Cola (); Cola cola2 = new Cola (); Cola cola3 = new Cola (); for (int minuto = 0 ; minuto < 600 ; minuto++) { if (llegada == minuto) { if (estado1==0) { estado1=1; salida1=minuto+7+(int)(Math.random()*5); } else { if (estado2==0) { estado2=1; salida2=minuto+7+(int)(Math.random()*5); } else { if (estado3==0) { estado3=1; salida3=minuto+7+(int)(Math.random()*5);

Page 34: Tutorial Java Ya 3

} else { if (cola1.cantidad()==6 && cola2.cantidad()==6 && cola3.cantidad()==6) { marchan++; } else { if (cola1.cantidad()<=cola2.cantidad() && cola1.cantidad()<=cola3.cantidad()) { cola1.insertar(minuto); } else { if (cola2.cantidad()<=cola3.cantidad()) { cola2.insertar(minuto); } else { cola3.insertar(minuto); } } } } } } llegada=minuto+ 2+ (int) (Math.random () * 2); } if (salida1 == minuto) { cantAte1++; estado1=0; if(!cola1.vacia()) { estado1=1; int m=cola1.extraer(); salida1=minuto+7+(int)(Math.random()*5); tiempoEnCola=tiempoEnCola+(minuto-m); cantidadEnCola++; } } if (salida2 == minuto) { cantAte2++; estado2=0; if(!cola2.vacia()) { estado2=1; int m=cola2.extraer(); salida2=minuto+7+(int)(Math.random()*5); tiempoEnCola=tiempoEnCola+(minuto-m); cantidadEnCola++; } } if (salida3 == minuto) { cantAte3++; estado3=0; if(!cola3.vacia()) { estado3=1;

Page 35: Tutorial Java Ya 3

int m=cola3.extraer(); salida3=minuto+7+(int)(Math.random()*5); tiempoEnCola=tiempoEnCola+(minuto-m); cantidadEnCola++; } } } l1.setText("Clientes atendidos por caja: caja1="+cantAte1+" caja2="+cantAte2+" caja3="+cantAte3); l2.setText("Se marchan sin hacer compras:"+marchan); if (cantidadEnCola>0) { int tiempoPromedio=tiempoEnCola/cantidadEnCola; l3.setText("Tiempo promedio en cola:"+tiempoPromedio); } } public static void main(String[] ar) { Supermercado super1=new Supermercado(); super1.setBounds(0,0,390,250); super1.setVisible(true); } }

46. Estructuras dinámicas: Listas genéricas

Continuando con el tema de listas trabajaremos con las listas genéricas. Una lista se comporta como genérica cuando las inserciones y extracciones se realizan en cualquier parte de la lista.Codificaremos una serie de métodos para administrar listas genéricas.

Métodos a desarrollar:Inserta un nodo en la posición (pos) y con la información que hay en el parámetro x. void insertar(int pos, int x)

Extrae la información del nodo de la posición indicada (pos). Se debe eliminar el nodo. int extraer(int pos)

Borra el nodo de la posición (pos). void borrar(int pos)

Intercambia las informaciones de los nodos de las posiciones pos1 y pos2. void intercambiar(int pos1,int pos2)

Retorna el valor del nodo con mayor información. int mayor()

Retorna la posición del nodo con mayor información. int posMayor()

Retorna la cantidad de nodos de la lista.

Page 36: Tutorial Java Ya 3

int cantidad()

Debe retornar true si la lista está ordenada de menor a mayor, false en caso contrario. boolean ordenada()

Debe retornar true si existe la información que llega en el parámetro, false en caso contrario. boolean existe(int info)

El método vacía debe retornar true si está vacía y false si no lo está. boolean vacia()

Programa:

public class ListaGenerica { class Nodo { int info; Nodo sig; } private Nodo raiz; public ListaGenerica () { raiz=null; } void insertar (int pos, int x) { if (pos <= cantidad () + 1) { Nodo nuevo = new Nodo (); nuevo.info = x; if (pos == 1){ nuevo.sig = raiz; raiz = nuevo; } else if (pos == cantidad () + 1) { Nodo reco = raiz; while (reco.sig != null) { reco = reco.sig; } reco.sig = nuevo; nuevo.sig = null; } else { Nodo reco = raiz; for (int f = 1 ; f <= pos - 2 ; f++)

Page 37: Tutorial Java Ya 3

reco = reco.sig; Nodo siguiente = reco.sig; reco.sig = nuevo; nuevo.sig = siguiente; } } }

public int extraer (int pos) { if (pos <= cantidad ()) { int informacion; if (pos == 1) { informacion = raiz.info; raiz = raiz.sig; } else { Nodo reco; reco = raiz; for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig; Nodo prox = reco.sig; reco.sig = prox.sig; informacion = prox.info; } return informacion; } else return Integer.MAX_VALUE; }

public void borrar (int pos) { if (pos <= cantidad ()) { if (pos == 1) { raiz = raiz.sig; } else { Nodo reco; reco = raiz; for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig; Nodo prox = reco.sig; reco.sig = prox.sig;

Page 38: Tutorial Java Ya 3

} } } public void intercambiar (int pos1, int pos2) { if (pos1 <= cantidad () && pos2 <= cantidad ()) { Nodo reco1 = raiz; for (int f = 1 ; f < pos1 ; f++) reco1 = reco1.sig; Nodo reco2 = raiz; for (int f = 1 ; f < pos2 ; f++) reco2 = reco2.sig; int aux = reco1.info; reco1.info = reco2.info; reco2.info = aux; } } public int mayor () { if (!vacia ()) { int may = raiz.info; Nodo reco = raiz.sig; while (reco != null) { if (reco.info > may) may = reco.info; reco = reco.sig; } return may; } else return Integer.MAX_VALUE; } public int posMayor() { if (!vacia ()) { int may = raiz.info; int x=1; int pos=x; Nodo reco = raiz.sig; while (reco != null){ if (reco.info > may) {

Page 39: Tutorial Java Ya 3

may = reco.info; pos=x; } reco = reco.sig; x++; } return pos; } else return Integer.MAX_VALUE; }

public int cantidad () { int cant = 0; Nodo reco = raiz; while (reco != null) { reco = reco.sig; cant++; } return cant; } public boolean ordenada() { if (cantidad()>1) { Nodo reco1=raiz; Nodo reco2=raiz.sig; while (reco2!=null) { if (reco2.info<reco1.info) { return false; } reco2=reco2.sig; reco1=reco1.sig; } } return true; } public boolean existe(int x) { Nodo reco=raiz; while (reco!=null) { if (reco.info==x)

Page 40: Tutorial Java Ya 3

return true; reco=reco.sig; } return false; } public boolean vacia () { if (raiz == null) return true; else return false; } public void imprimir () { Nodo reco = raiz; while (reco != null) { System.out.print (reco.info + "-"); reco = reco.sig; } System.out.println(); } public static void main(String[] ar) { ListaGenerica lg=new ListaGenerica(); lg.insertar (1, 10); lg.insertar (2, 20); lg.insertar (3, 30); lg.insertar (2, 15); lg.insertar (1, 115); lg.imprimir (); System.out.println ("Luego de Borrar el primero"); lg.borrar (1); lg.imprimir (); System.out.println ("Luego de Extraer el segundo"); lg.extraer (2); lg.imprimir (); System.out.println ("Luego de Intercambiar el primero con el tercero"); lg.intercambiar (1, 3);

Page 41: Tutorial Java Ya 3

lg.imprimir (); if (lg.existe(10)) System.out.println("Se encuentra el 20 en la lista"); else System.out.println("No se encuentra el 20 en la lista"); System.out.println("La posición del mayor es:"+lg.posMayor()); if (lg.ordenada()) System.out.println("La lista está ordenada de menor a mayor"); else System.out.println("La lista no está ordenada de menor a mayor"); }}

Para insertar en una determinada posición dentro de la lista: void insertar (int pos, int x)

Primero con un if verificamos que exista esa posición en la lista (por ejemplo si la lista tiene 4 nodos podemos insertar hasta la posición 5, es decir uno más allá del último): if (pos <= cantidad () + 1) {

Si ingresa al if ya podemos crear el nodo: Nodo nuevo = new Nodo (); nuevo.info = x;

Ahora debemos analizar si la inserción es al principio de la lista, al final o en medio ya que los enlaces varían según donde se lo inserta. Para saber si se inserta al principio de la lista preguntamos si en pos llega un 1: if (pos == 1){

Si llega un 1 luego enlazamos el puntero sig del nodo que creamos con la dirección del primer nodo de la lista (raiz apunta siempre al primer nodo de la lista) y luego desplazamos raiz al nodo que acabamos de crear: nuevo.sig = raiz; raiz = nuevo;

Si no se inserta al principio de la lista preguntamos si se inserta al final: if (pos == cantidad () + 1) {

En caso de insertarse al final recorremos la lista hasta el último nodo: Nodo reco = raiz; while (reco.sig != null) { reco = reco.sig; }

Page 42: Tutorial Java Ya 3

y enlazamos el puntero sig del último nodo de la lista con la dirección del nodo que acabamos de crear (disponemos en sig del nodo creado el valor null ya que no hay otro nodo más adelante) reco.sig = nuevo; nuevo.sig = null;

Si no se inserta al principio o al final significa que tenemos que insertar en medio de la lista.Disponemos un for donde avanzamos un puntero auxiliar y nos detenemos una posición antes a donde tenemos que insertarlo:

for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig;

Disponemos otro puntero auxiliar que apunte al nodo próximo a donde está apuntando reco. Ahora enlazamos el puntero sig del nodo apuntado por reco con la dirección del nodo creado y el puntero sig del nodo creado con la dirección del nodo siguiente: Nodo siguiente = reco.sig; reco.sig = nuevo; nuevo.sig = siguiente;

El método extraer recibe como parámetro la posición del nodo a extraer: public int extraer (int pos) {

Primero verificamos que la posición exista en la lista: if (pos <= cantidad ()) {

En caso que exista verificamos si el nodo a extraer es el primero de la lista (este análisis debe hacerse ya que si es el primero de la lista se modifica el puntero raiz): if (pos == 1) {

Si es el primero guardamos en una variable auxiliar la información del nodo y avanzamos el puntero raiz: informacion = raiz.info; raiz = raiz.sig;

Si el nodo a extraer no está al principio de la lista avanzamos con una estructura repetitiva hasta el nodo anterior a extraer: for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig;

Luego definimos otro puntero auxiliar y lo disponemos en el siguiente nodo a donde está apuntando reco: Nodo prox = reco.sig;

Ahora enlazamos el puntero sig del nodo apuntado por reco al nodo siguiente del nodo apuntado por prox (es decir el nodo apuntado por prox queda fuera de la lista): reco.sig = prox.sig;

El método borrar es muy similar al método extraer con la diferencia de que no retorna valor: public void borrar (int pos) { if (pos <= cantidad ()) { if (pos == 1) {

Page 43: Tutorial Java Ya 3

raiz = raiz.sig; } else { Nodo reco; reco = raiz; for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig; Nodo prox = reco.sig; reco.sig = prox.sig; } } }

El método intercambiar recibe dos enteros que representan las posiciones de los nodos que queremos intercambiar sus informaciones: public void intercambiar (int pos1, int pos2) {

Mediante un if verificamos que las dos posiciones existan en la lista: if (pos1 <= cantidad () && pos2 <= cantidad ()) {

Definimos un puntero auxiliar llamado reco1, lo inicializamos con la dirección del primer nodo y mediante un for avanzamos hasta la posición almacenada en pos1: Nodo reco1 = raiz; for (int f = 1 ; f < pos1 ; f++) reco1 = reco1.sig;

De forma similar con un segundo puntero auxiliar avanzamos hasta la posición indicada por pos2: Nodo reco2 = raiz; for (int f = 1 ; f < pos2 ; f++) reco2 = reco2.sig;

Por último intercambiamos las informaciones que almacenan cada nodo: int aux = reco1.info; reco1.info = reco2.info; reco2.info = aux;

El método que retorna el mayor de la lista: public int mayor () {

Verificamos que la lista no esté vacía: if (!vacia ()) {

Suponemos que el mayor es el primero de la lista e inicializamos un puntero auxiliar con la dirección del segundo nodo de la lista: int may = raiz.info; Nodo reco = raiz.sig;

Mediante una estructura repetitiva recorremos toda la lista: while (reco != null) {

Page 44: Tutorial Java Ya 3

Cada vez que encontramos un nodo con información mayor que la variable may la actualizamos con este nuevo valor y avanzamos el puntero reco para visitar el siguiente nodo: if (reco.info > may) may = reco.info; reco = reco.sig;

Fuera de la estructura repetitiva retornamos el mayor: return may;

El método que retorna la posición del mayor es similar al anterior con la salvedad que debemos almacenar en otro auxiliar la posición donde se almacena el mayor: public int posMayor() { if (!vacia ()) { int may = raiz.info; int x=1; int pos=x; Nodo reco = raiz.sig; while (reco != null){ if (reco.info > may) { may = reco.info; pos=x; } reco = reco.sig; x++; } return pos; } else return Integer.MAX_VALUE; }

El método que debe retornar si está ordenada la lista de menor a mayor es: public boolean ordenada() {

Lo primero que verificamos si la lista tiene más de un nodo significa que debemos controlarla: if (cantidad()>1) {

Disponemos dos punteros auxiliares con las direcciones del primer y segundo nodo de la lista: Nodo reco1=raiz; Nodo reco2=raiz.sig;

Mediante un while mientras no se finaliza la lista: while (reco2!=null) {

controlamos si la información del segundo nodo es menor al nodo anterior significa que la lista no está ordenada y podemos parar el análisis retornando un false if (reco2.info<reco1.info) { return false;

Dentro del while avanzamos los dos punteros a sus nodos siguientes respectivamente. reco2=reco2.sig; reco1=reco1.sig;

Fuera del while retornamos true indicando que la lista está ordenada de menor a mayor return true;

Page 45: Tutorial Java Ya 3

El método existe:

public boolean existe(int x) {

Mediante un while recorremos la la lista: Nodo reco=raiz; while (reco!=null) {

y en cada nodo que visitamos controlamos si el parámetro x es igual a la información del nodo, en caso afirmativo salimos del método retornando true: if (reco.info==x) return true; reco=reco.sig;

Fuera del while retornamos false indicando que ningún nodo coincide con el parámetro x: return false;

Problemas propuestos1. Plantear una clase para administrar una lista genérica implementando los siguientes

métodos:a) Insertar un nodo al principio de la lista.b) Insertar un nodo al final de la lista.c) Insertar un nodo en la segunda posición. Si la lista está vacía no se inserta el nodo.d) Insertar un nodo en la ante última posición.e) Borrar el primer nodo.f) Borrar el segundo nodo.g) Borrar el último nodo.h) Borrar el nodo con información mayor.

Solución

public class ListaGenerica { class Nodo { int info; Nodo sig; } private Nodo raiz; public ListaGenerica () { raiz=null; } void insertarPrimero(int x) { Nodo nuevo = new Nodo (); nuevo.info = x; nuevo.sig=raiz; raiz=nuevo; }

Page 46: Tutorial Java Ya 3

public void insertarUtlimo(int x) { Nodo nuevo = new Nodo (); nuevo.info = x; if (raiz==null) raiz=nuevo; else { Nodo reco=raiz; while (reco.sig!=null) { reco=reco.sig; } reco.sig=nuevo; } } public void insertarSegundo(int x) { if (raiz!=null) { Nodo nuevo = new Nodo (); nuevo.info = x; if (raiz.sig==null) { //Hay un solo nodo. raiz.sig=nuevo; } else { nuevo.sig=raiz.sig; raiz.sig=nuevo; } } } public void insertarAnteUltimo(int x) { if (raiz!=null) { Nodo nuevo = new Nodo (); nuevo.info = x; if (raiz.sig==null) { //Hay un solo nodo. nuevo.sig=raiz; raiz=nuevo; } else { Nodo atras=raiz; Nodo reco=raiz.sig; while (reco.sig!=null) { atras=reco; reco=reco.sig; } nuevo.sig=atras.sig; atras.sig=nuevo; } } } public void borrarPrimero() {

Page 47: Tutorial Java Ya 3

if (raiz!=null) { raiz=raiz.sig; } } public void borrarSegundo() { if (raiz!=null) { if (raiz.sig!=null) { Nodo tercero=raiz.sig; tercero=tercero.sig; raiz.sig=tercero; } } } public void borrarUltimo () { if (raiz!=null) { if (raiz.sig==null) { raiz=null; } else { Nodo reco=raiz.sig; Nodo atras=reco; while(reco.sig!=null) { atras=reco; reco=reco.sig; } atras.sig=null; } } } public void imprimir () { Nodo reco = raiz; while (reco != null) { System.out.print (reco.info + "-"); reco = reco.sig; } System.out.println(); } public void borrarMayor() { if (raiz!=null) { Nodo reco=raiz; int may=raiz.info; while (reco!=null) { if (reco.info>may) { may=reco.info; } reco=reco.sig; }

Page 48: Tutorial Java Ya 3

reco=raiz; Nodo atras=raiz; while (reco!=null) { if (reco.info==may) { if (reco==raiz) { raiz=raiz.sig; atras=raiz; reco=raiz; } else { atras.sig=reco.sig; reco=reco.sig; } } else { atras=reco; reco=reco.sig; } } } } public static void main(String[] ar) { ListaGenerica lg=new ListaGenerica(); lg.insertarPrimero (10); lg.insertarPrimero(45); lg.insertarPrimero(23); lg.insertarPrimero(89); lg.imprimir(); System.out.println("Insertamos un nodo al final:"); lg.insertarUtlimo(160); lg.imprimir(); System.out.println("Insertamos un nodo en la segunda posición:"); lg.insertarSegundo(13); lg.imprimir(); System.out.println("Insertamos un nodo en la anteultima posición:"); lg.insertarAnteUltimo(600); lg.imprimir(); System.out.println("Borramos el primer nodo de la lista:"); lg.borrarPrimero(); lg.imprimir(); System.out.println("Borramos el segundo nodo de la lista:"); lg.borrarSegundo(); lg.imprimir(); System.out.println("Borramos el ultimo nodo de la lista:"); lg.borrarUltimo(); lg.imprimir(); System.out.println("Borramos el mayor de la lista:"); lg.borrarMayor();

Page 49: Tutorial Java Ya 3

lg.imprimir(); }}

47. Estructuras dinámicas: Listas genéricas ordenadas

Una lista genérica es ordenada si cuando insertamos información en la lista queda ordenada respecto al campo info (sea de menor a mayor o a la inversa)Ejemplo:listaOrdenada.insertar(10)

listaOrdenada.insertar(5)

listaOrdenada.insertar(7)

listaOrdenada.insertar(50)

Podemos observar que si recorremos la lista podemos acceder a la información de menor a mayor.No se requiere un método para ordenar la lista, sino que siempre permanece ordenada, ya que se inserta ordenada.

Programa:

public class ListaOrdenada { class Nodo {

Page 50: Tutorial Java Ya 3

int info; Nodo sig; } private Nodo raiz; public ListaOrdenada() { raiz=null; } void insertar(int x) { Nodo nuevo = new Nodo (); nuevo.info = x; if (raiz==null) { raiz=nuevo; } else { if (x<raiz.info) { nuevo.sig=raiz; raiz=nuevo; } else { Nodo reco=raiz; Nodo atras=raiz; while (x>=reco.info && reco.sig!=null) { atras=reco; reco=reco.sig; } if (x>=reco.info) { reco.sig=nuevo; } else { nuevo.sig=reco; atras.sig=nuevo; } } } }

public void imprimir () { Nodo reco = raiz; while (reco != null) { System.out.print (reco.info + "-"); reco = reco.sig;

Page 51: Tutorial Java Ya 3

} System.out.println(); } public static void main(String[] ar) { ListaOrdenada lo=new ListaOrdenada(); lo.insertar(10); lo.insertar(5); lo.insertar(7); lo.insertar(50); lo.imprimir(); }}

El método insertar lo resolvemos de la siguiente forma:Creamos primeramente el nodo, ya que siempre se insertará la información en la lista: Nodo nuevo = new Nodo (); nuevo.info = x;

Se puede presentar las siguientes situaciones, si está vacía, lo insertamos inmediatamente: if (raiz==null) { raiz=nuevo; } else {

Si no está vacía la lista, verificamos si lo debemos insertar en la primera posición de la lista (analizamos si la información a insertar es menor a lo apuntado por raiz en el campo info): if (x<raiz.info) { nuevo.sig=raiz; raiz=nuevo; } else {

Sino analizamos si lo debemos insertar en medio o al final de la lista.Mientras la información a insertar sea mayor o igual a la información del nodo que visitamos ( x>=reco.info) y no lleguemos al final de la lista (reco.sig!=null) avanzamos reco al siguiente nodo y fijamos un puntero en el nodo anterior (atras) Nodo reco=raiz; Nodo atras=raiz; while (x>=reco.info && reco.sig!=null) { atras=reco; reco=reco.sig; }

Cuando salimos del while si la condición (x>=reco.info) continua siendo verdadera significa que se inserta al final de la lista, en caso contrario se inserta en medio de la lista: if (x>=reco.info) { reco.sig=nuevo; } else { nuevo.sig=reco; atras.sig=nuevo; }

Page 52: Tutorial Java Ya 3

48. Estructuras dinámicas: Listas genéricas doblemente encadenadas

A las listas vistas hasta el momento podemos recorrerlas solamente en una dirección (Listas simplemente encadenadas). Hay problemas donde se requiere recorrer la lista en ambas direcciones, en estos casos el empleo de listas doblemente encadenadas es recomendable.Como ejemplo pensemos que debemos almacenar un menú de opciones en una lista, la opción a seleccionar puede ser la siguiente o la anterior, podemos desplazarnos en ambas direcciones.Representación gráfica de una lista doblemente encadenada:

Observemos que una lista doblemente encadenada tiene dos punteros por cada nodo, uno apunta al nodo siguiente y otro al nodo anterior.Seguimos teniendo un puntero (raiz) que tiene la dirección del primer nodo.El puntero sig del último nodo igual que las listas simplemente encadenadas apunta a null, y el puntero ant del primer nodo apunta a null.Se pueden plantear Listas tipo pila, cola y genéricas con enlace doble.Hay que tener en cuenta que el requerimiento de memoria es mayor en las listas doblemente encadenadas ya que tenemos dos punteros por nodo.La estructura del nodo es: class Nodo { int info; Nodo sig, ant; }

Resolveremos algunos métodos para administrar listas genéricas empleando listas doblemente encadenadas para analizar la mecánica de enlace de nodos.Muchos de los métodos, para listas simple y doblemente encadenadas no varía, como por ejemplo: el constructor, vacia, cantidad, etc.

Programa:

public class ListaGenerica { class Nodo { int info; Nodo ant,sig; } private Nodo raiz; public ListaGenerica () { raiz=null;

Page 53: Tutorial Java Ya 3

} void insertar (int pos, int x) { if (pos <= cantidad () + 1) { Nodo nuevo = new Nodo (); nuevo.info = x; if (pos == 1){ nuevo.sig = raiz; if (raiz!=null) raiz.ant=nuevo; raiz = nuevo; } else if (pos == cantidad () + 1) { Nodo reco = raiz; while (reco.sig != null) { reco = reco.sig; } reco.sig = nuevo; nuevo.ant=reco; nuevo.sig = null; } else { Nodo reco = raiz; for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig; Nodo siguiente = reco.sig; reco.sig = nuevo; nuevo.ant=reco; nuevo.sig = siguiente; siguiente.ant=nuevo; } } }

public int extraer (int pos) { if (pos <= cantidad ()) { int informacion; if (pos == 1) { informacion = raiz.info; raiz = raiz.sig; if (raiz!=null) raiz.ant=null;

Page 54: Tutorial Java Ya 3

} else { Nodo reco; reco = raiz; for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig; Nodo prox = reco.sig; reco.sig = prox.sig; Nodo siguiente=prox.sig; if (siguiente!=null) siguiente.ant=reco; informacion = prox.info; } return informacion; } else return Integer.MAX_VALUE; }

public void borrar (int pos) { if (pos <= cantidad ()) { if (pos == 1) { raiz = raiz.sig; if (raiz!=null) raiz.ant=null; } else { Nodo reco; reco = raiz; for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig; Nodo prox = reco.sig; prox=prox.sig; reco.sig = prox; if (prox!=null) prox.ant=reco; } } } public void intercambiar (int pos1, int pos2) { if (pos1 <= cantidad () && pos2 <= cantidad ()) {

Page 55: Tutorial Java Ya 3

Nodo reco1 = raiz; for (int f = 1 ; f < pos1 ; f++) reco1 = reco1.sig; Nodo reco2 = raiz; for (int f = 1 ; f < pos2 ; f++) reco2 = reco2.sig; int aux = reco1.info; reco1.info = reco2.info; reco2.info = aux; } } public int mayor () { if (!vacia ()) { int may = raiz.info; Nodo reco = raiz.sig; while (reco != null) { if (reco.info > may) may = reco.info; reco = reco.sig; } return may; } else return Integer.MAX_VALUE; } public int posMayor() { if (!vacia ()) { int may = raiz.info; int x=1; int pos=x; Nodo reco = raiz.sig; while (reco != null){ if (reco.info > may) { may = reco.info; pos=x; } reco = reco.sig; x++; } return pos;

Page 56: Tutorial Java Ya 3

} else return Integer.MAX_VALUE; }

public int cantidad () { int cant = 0; Nodo reco = raiz; while (reco != null) { reco = reco.sig; cant++; } return cant; } public boolean ordenada() { if (cantidad()>1) { Nodo reco1=raiz; Nodo reco2=raiz.sig; while (reco2!=null) { if (reco2.info<reco1.info) { return false; } reco2=reco2.sig; reco1=reco1.sig; } } return true; } public boolean existe(int x) { Nodo reco=raiz; while (reco!=null) { if (reco.info==x) return true; reco=reco.sig; } return false; } public boolean vacia ()

Page 57: Tutorial Java Ya 3

{ if (raiz == null) return true; else return false; } public void imprimir () { Nodo reco = raiz; while (reco != null) { System.out.print (reco.info + "-"); reco = reco.sig; } System.out.println(); } public static void main(String[] ar) { ListaGenerica lg=new ListaGenerica(); lg.insertar (1, 10); lg.insertar (2, 20); lg.insertar (3, 30); lg.insertar (2, 15); lg.insertar (1, 115); lg.imprimir (); System.out.println ("Luego de Borrar el primero"); lg.borrar (1); lg.imprimir (); System.out.println ("Luego de Extraer el segundo"); lg.extraer (2); lg.imprimir (); System.out.println ("Luego de Intercambiar el primero con el tercero"); lg.intercambiar (1, 3); lg.imprimir (); if (lg.existe(10)) System.out.println("Se encuentra el 20 en la lista"); else System.out.println("No se encuentra el 20 en la lista");

Page 58: Tutorial Java Ya 3

System.out.println("La posición del mayor es:"+lg.posMayor()); if (lg.ordenada()) System.out.println("La lista está ordenada de menor a mayor"); else System.out.println("La lista no está ordenada de menor a mayor"); }}

Para insertar en una determinada posición dentro de la lista: void insertar (int pos, int x)

Primero con un if verificamos que exista esa posición en la lista (por ejemplo si la lista tiene 4 nodos podemos insertar hasta la posición 5, es decir uno más allá del último): if (pos <= cantidad () + 1) {

Si ingresa al if ya podemos crear el nodo: Nodo nuevo = new Nodo (); nuevo.info = x;

Ahora debemos analizar si la inserción es al principio de la lista, al final o en medio ya que los enlaces varían según donde se lo inserta. Para saber si se inserta al principio de la lista preguntamos si en pos llega un 1: if (pos == 1){

Si llega un 1 luego enlazamos el puntero sig del nodo que creamos con la dirección del primer nodo de la lista (raiz apunta siempre al primer nodo de la lista)Verificamos si raiz está apuntando actualmente a un nodo, en caso afirmativo enlazamos el puntero ant con el nodo que acabamos de crear y luego desplazamos raiz al nodo creado: nuevo.sig = raiz; if (raiz!=null) raiz.ant=nuevo; raiz = nuevo;

Si no se inserta al principio de la lista preguntamos si se inserta al final: if (pos == cantidad () + 1) {

En caso de insertarse al final recorremos la lista hasta el último nodo: Nodo reco = raiz; while (reco.sig != null) { reco = reco.sig; }

y enlazamos el puntero sig del último nodo de la lista con la dirección del nodo que acabamos de crear (disponemos en sig del nodo creado el valor null ya que no hay otro nodo más adelante) El

Page 59: Tutorial Java Ya 3

puntero ant del nodo que creamos lo enlazamos con el nodo que era último hasta este momento y está siendo apuntado por reco: reco.sig = nuevo; nuevo.ant=reco; nuevo.sig = null;

Si no se inserta al principio o al final significa que tenemos que insertar en medio de la lista.Disponemos un for donde avanzamos un puntero auxiliar y nos detenemos una posición antes a donde tenemos que insertarlo:

for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig;

Disponemos otro puntero auxiliar que apunte al nodo próximo a donde está apuntando reco. Ahora enlazamos el puntero sig del nodo apuntado por reco con la dirección del nodo creado y el puntero sig del nodo creado con la dirección del nodo siguiente. El puntero ant del nodo apuntado por nuevo lo enlazamos con el nodo apuntado por raiz y el puntero ant del nodo apuntado por siguiente lo apuntamos a nuevo (con esto tenemos actualizados los cuatro punteros internos a la lista): Nodo siguiente = reco.sig; reco.sig = nuevo; nuevo.ant=reco; nuevo.sig = siguiente; siguiente.ant=nuevo;

El método extraer recibe como parámetro la posición del nodo a extraer: public int extraer (int pos) {

Primero verificamos que la posición exista en la lista: if (pos <= cantidad ()) {

En caso que exista verificamos si el nodo a extraer es el primero de la lista (este análisis debe hacerse ya que si es el primero de la lista se modifica el puntero raiz): if (pos == 1) {

Si es el primero guardamos en una variable auxiliar la información del nodo y avanzamos el puntero raiz, luego si raiz apunta a un nodo disponemos el puntero ant de dicho nodo a null: informacion = raiz.info; raiz = raiz.sig; if (raiz!=null) raiz.ant=null;

Si el nodo a extraer no está al principio de la lista avanzamos con una estructura repetitiva hasta el nodo anterior a extraer: for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig;

Luego definimos otro puntero auxiliar y lo disponemos en el siguiente nodo a donde está apuntando reco: Nodo prox = reco.sig;

Ahora enlazamos el puntero sig del nodo apuntado por reco al nodo siguiente del nodo apuntado por prox (es decir el nodo apuntado por prox queda fuera de la lista) disponemos finalmente otro

Page 60: Tutorial Java Ya 3

puntero llamado siguiente que apunte al nodo que se encuentra una posición más adelante del nodo apuntado por prox, si dicho puntero apunta a un nodo actualizamos el puntero ant de dicho nodo con la dirección del nodo apuntado por reco: reco.sig = prox.sig; Nodo siguiente=prox.sig; if (siguiente!=null) siguiente.ant=reco; informacion = prox.info;

El método borrar es muy similar al método extraer con la diferencia de que no retorna valor: public void borrar (int pos) { if (pos <= cantidad ()) { if (pos == 1) { raiz = raiz.sig; if (raiz!=null) raiz.ant=null; } else { Nodo reco; reco = raiz; for (int f = 1 ; f <= pos - 2 ; f++) reco = reco.sig; Nodo prox = reco.sig; prox=prox.sig; reco.sig = prox; if (prox!=null) prox.ant=reco; } } }

El método intercambiar recibe dos enteros que representan las posiciones de los nodos que queremos intercambiar sus informaciones: public void intercambiar (int pos1, int pos2) {

Mediante un if verificamos que las dos posiciones existan en la lista: if (pos1 <= cantidad () && pos2 <= cantidad ()) {

Definimos un puntero auxiliar llamado reco1, lo inicializamos con la dirección del primer nodo y mediante un for avanzamos hasta la posición almacenada en pos1: Nodo reco1 = raiz; for (int f = 1 ; f < pos1 ; f++) reco1 = reco1.sig;

De forma similar con un segundo puntero auxiliar avanzamos hasta la posición indicada por pos2: Nodo reco2 = raiz; for (int f = 1 ; f < pos2 ; f++)

Page 61: Tutorial Java Ya 3

reco2 = reco2.sig;Por último intercambiamos las informaciones que almacenan cada nodo: int aux = reco1.info; reco1.info = reco2.info; reco2.info = aux;

El método que retorna el mayor de la lista: public int mayor () {

Verificamos que la lista no esté vacía: if (!vacia ()) {

Suponemos que el mayor es el primero de la lista e inicializamos un puntero auxiliar con la dirección del segundo nodo de la lista: int may = raiz.info; Nodo reco = raiz.sig;

Mediante una estructura repetitiva recorremos toda la lista: while (reco != null) {

Cada vez que encontramos un nodo con información mayor que la variable may la actualizamos con este nuevo valor y avanzamos el puntero reco para visitar el siguiente nodo: if (reco.info > may) may = reco.info; reco = reco.sig;

Fuera de la estructura repetitiva retornamos el mayor: return may;

El método que retorna la posición del mayor es similar al anterior con la salvedad que debemos almacenar en otro auxiliar la posición donde se almacena el mayor: public int posMayor() { if (!vacia ()) { int may = raiz.info; int x=1; int pos=x; Nodo reco = raiz.sig; while (reco != null){ if (reco.info > may) { may = reco.info; pos=x; } reco = reco.sig; x++; } return pos; } else return Integer.MAX_VALUE; }

El método que debe retornar si está ordenada la lista de menor a mayor es:

Page 62: Tutorial Java Ya 3

public boolean ordenada() {

Lo primero que verificamos si la lista tiene más de un nodo significa que debemos controlarla: if (cantidad()>1) {

Disponemos dos punteros auxiliares con las direcciones del primer y segundo nodo de la lista: Nodo reco1=raiz; Nodo reco2=raiz.sig;

Mediante un while mientras no se finaliza la lista: while (reco2!=null) {

controlamos si la información del segundo nodo es menor al nodo anterior significa que la lista no está ordenada y podemos parar el análisis retornando un false if (reco2.info<reco1.info) { return false;

Dentro del while avanzamos los dos punteros a sus nodos siguientes respectivamente. reco2=reco2.sig; reco1=reco1.sig;

Fuera del while retornamos true indicando que la lista está ordenada de menor a mayor return true;

El método existe:

public boolean existe(int x) {

Mediante un while recorremos la la lista: Nodo reco=raiz; while (reco!=null) {

y en cada nodo que visitamos controlamos si el parámetro x es igual a la información del nodo, en caso afirmativo salimos del método retornando true: if (reco.info==x) return true; reco=reco.sig;

Fuera del while retornamos false indicando que ningún nodo coincide con el parámetro x: return false;

Problemas propuestos1. Plantear una clase para administrar una lista genérica doblemente encadenada

implementando los siguientes métodos:a) Insertar un nodo al principio de la lista.b) Insertar un nodo al final de la lista.c) Insertar un nodo en la segunda posición. Si la lista está vacía no se inserta el nodo.d) Insertar un nodo en la ante última posición.e) Borrar el primer nodo.f) Borrar el segundo nodo.g) Borrar el último nodo.h) Borrar el nodo con información mayor.

Solución

Page 63: Tutorial Java Ya 3

public class ListaGenericaDoble { class Nodo { int info; Nodo ant,sig; } private Nodo raiz; public ListaGenericaDoble () { raiz=null; } void insertarPrimero(int x) { Nodo nuevo = new Nodo (); nuevo.info = x; nuevo.sig=raiz; if (raiz!=null) raiz.ant=nuevo; raiz=nuevo; }

public void insertarUtlimo(int x) { Nodo nuevo = new Nodo (); nuevo.info = x; if (raiz==null) raiz=nuevo; else { Nodo reco=raiz; while (reco.sig!=null) { reco=reco.sig; } reco.sig=nuevo; nuevo.ant=reco; } } public void insertarSegundo(int x) { if (raiz!=null) { Nodo nuevo = new Nodo (); nuevo.info = x; if (raiz.sig==null) { //Hay un solo nodo. raiz.sig=nuevo; nuevo.ant=raiz; } else { Nodo tercero=raiz.sig; nuevo.sig=tercero; tercero.ant=nuevo;

Page 64: Tutorial Java Ya 3

raiz.sig=nuevo; nuevo.ant=raiz; } } } public void insertarAnteUltimo(int x) { if (raiz!=null) { Nodo nuevo = new Nodo (); nuevo.info = x; if (raiz.sig==null) { //Hay un solo nodo. nuevo.sig=raiz; raiz=nuevo; } else { Nodo reco=raiz; while (reco.sig!=null) { reco=reco.sig; } Nodo anterior=reco.ant; nuevo.sig=reco; nuevo.ant=anterior; anterior.sig=nuevo; reco.ant=nuevo; } } } public void borrarPrimero() { if (raiz!=null) { raiz=raiz.sig; } } public void borrarSegundo() { if (raiz!=null) { if (raiz.sig!=null) { Nodo tercero=raiz.sig; tercero=tercero.sig; raiz.sig=tercero; if (tercero!=null) tercero.ant=raiz; } } } public void borrarUltimo () { if (raiz!=null) { if (raiz.sig==null) { raiz=null;

Page 65: Tutorial Java Ya 3

} else { Nodo reco=raiz; while(reco.sig!=null) { reco=reco.sig; } reco=reco.ant; reco.sig=null; } } } public void imprimir () { Nodo reco = raiz; while (reco != null) { System.out.print (reco.info + "-"); reco = reco.sig; } System.out.println(); } public void borrarMayor() { if (raiz!=null) { Nodo reco=raiz; int may=raiz.info; while (reco!=null) { if (reco.info>may) { may=reco.info; } reco=reco.sig; } reco=raiz; while (reco!=null) { if (reco.info==may) { if (reco==raiz) { raiz=raiz.sig; if (raiz!=null) raiz.ant=null; reco=raiz; } else { Nodo atras=reco.ant; atras.sig=reco.sig; reco=reco.sig; if (reco!=null) reco.ant=atras; } } else { reco=reco.sig; } } }

Page 66: Tutorial Java Ya 3

} public static void main(String[] ar) { ListaGenericaDoble lg=new ListaGenericaDoble(); lg.insertarPrimero (10); lg.insertarPrimero(45); lg.insertarPrimero(23); lg.insertarPrimero(89); lg.imprimir(); System.out.println("Insertamos un nodo al final:"); lg.insertarUtlimo(160); lg.imprimir(); System.out.println("Insertamos un nodo en la segunda posición:"); lg.insertarSegundo(13); lg.imprimir(); System.out.println("Insertamos un nodo en la anteultima posición:"); lg.insertarAnteUltimo(600); lg.imprimir(); System.out.println("Borramos el primer nodo de la lista:"); lg.borrarPrimero(); lg.imprimir(); System.out.println("Borramos el segundo nodo de la lista:"); lg.borrarSegundo(); lg.imprimir(); System.out.println("Borramos el ultimo nodo de la lista:"); lg.borrarUltimo(); lg.imprimir(); System.out.println("Borramos el mayor de la lista:"); lg.borrarMayor(); lg.imprimir(); }}

49. Estructuras dinámicas: Listas genéricas circulares

Una lista circular simplemente encadenada la podemos representar gráficamente:

Page 67: Tutorial Java Ya 3

Observemos que el puntero sig del último nodo apunta al primer nodo. En este tipo de listas si avanzamos raiz no perdemos la referencia al nodo anterior ya que es un círculo.Una lista circular puede también ser doblemente encadenada:

El puntero ant del primer nodo apunta al último nodo de la lista y el puntero sig del último nodo de la lista apunta al primero.Resolveremos algunos métodos para administrar listas genéricas circulares doblemente encadenadas para analizar la mecánica de enlace de nodos.

Programa:

public class ListaCircular { class Nodo { int info; Nodo ant,sig; } private Nodo raiz; public ListaCircular () { raiz=null; } public void insertarPrimero(int x) { Nodo nuevo=new Nodo(); nuevo.info=x; if (raiz==null) { nuevo.sig=nuevo; nuevo.ant=nuevo;

Page 68: Tutorial Java Ya 3

raiz=nuevo; } else { Nodo ultimo=raiz.ant; nuevo.sig=raiz; nuevo.ant=ultimo; raiz.ant=nuevo; ultimo.sig=nuevo; raiz=nuevo; } } public void insertarUltimo(int x) { Nodo nuevo=new Nodo(); nuevo.info=x; if (raiz==null) { nuevo.sig=nuevo; nuevo.ant=nuevo; raiz=nuevo; } else { Nodo ultimo=raiz.ant; nuevo.sig=raiz; nuevo.ant=ultimo; raiz.ant=nuevo; ultimo.sig=nuevo; } } public boolean vacia () { if (raiz == null) return true; else return false; } public void imprimir () { if (!vacia()) { Nodo reco=raiz; do { System.out.print (reco.info + "-"); reco = reco.sig;

Page 69: Tutorial Java Ya 3

} while (reco!=raiz); System.out.println(); } } public int cantidad () { int cant = 0; if (!vacia()) { Nodo reco=raiz; do { cant++; reco = reco.sig; } while (reco!=raiz); } return cant; } public void borrar (int pos) { if (pos <= cantidad ()) { if (pos == 1) { if (cantidad()==1) { raiz=null; } else { Nodo ultimo=raiz.ant; raiz = raiz.sig; ultimo.sig=raiz; raiz.ant=ultimo; } } else { Nodo reco = raiz; for (int f = 1 ; f <= pos - 1 ; f++) reco = reco.sig; Nodo anterior = reco.ant; reco=reco.sig; anterior.sig=reco; reco.ant=anterior; } } }

Page 70: Tutorial Java Ya 3

public static void main(String[] ar) { ListaCircular lc=new ListaCircular(); lc.insertarPrimero(100); lc.insertarPrimero(45); lc.insertarPrimero(12); lc.insertarPrimero(4); System.out.println("Luego de insertar 4 nodos al principio"); lc.imprimir(); lc.insertarUltimo(250); lc.insertarUltimo(7); System.out.println("Luego de insertar 2 nodos al final"); lc.imprimir(); System.out.println("Cantidad de nodos:"+lc.cantidad()); System.out.println("Luego de borrar el de la primer posición:"); lc.borrar(1); lc.imprimir(); System.out.println("Luego de borrar el de la cuarta posición:"); lc.borrar(4); lc.imprimir(); }}

Para insertar al principio de una lista circular doblemente encadenada:

public void insertarPrimero(int x) {

Creamos un nodo y guardamos la información: Nodo nuevo=new Nodo(); nuevo.info=x;

Si la lista está vacía luego tanto el puntero sig y ant apuntan a si mismo ya que debe ser circular (y raiz apunta al nodo creado): if (raiz==null) { nuevo.sig=nuevo; nuevo.ant=nuevo; raiz=nuevo;

En caso que la lista no esté vacía disponemos un puntero al final de la lista (el puntero ant del primer nodo tiene dicha dirección): } else { Nodo ultimo=raiz.ant;

El nodo a insertar lo enlazamos previo al nodo apuntado por raiz:

Page 71: Tutorial Java Ya 3

nuevo.sig=raiz; nuevo.ant=ultimo; raiz.ant=nuevo; ultimo.sig=nuevo;

Finalmente hacemos que raiz apunte al nodo creado luego de haber hecho todos los enlaces: raiz=nuevo;

Para insertar un nodo al final de la lista:

public void insertarUltimo(int x) {

El algoritmo es idéntico al método que inserta al principio con la salvedad que no desplazamos raiz con la dirección del nodo creado (es decir al insertar en la posición anterior del primer nodo lo que estamos haciendo realmente es insertar al final de la lista): Nodo nuevo=new Nodo(); nuevo.info=x; if (raiz==null) { nuevo.sig=nuevo; nuevo.ant=nuevo; raiz=nuevo; } else { Nodo ultimo=raiz.ant; nuevo.sig=raiz; nuevo.ant=ultimo; raiz.ant=nuevo; ultimo.sig=nuevo; } }

Para imprimir la lista ya no podemos disponer un puntero reco que apunte al primer nodo y que se detenga cuando encuentre un nodo que el atributo sig almacene null.

public void imprimir ()

Si la lista no está vacía disponemos un puntero en el primer nodo y utilizamos un do/while para recorrer la lista. La condición del do/while es que se repita mientras el puntero reco sea distinto a raiz (es decir que no haya dado toda la vuelta a la lista): if (!vacia()) { Nodo reco=raiz; do { System.out.print (reco.info + "-"); reco = reco.sig; } while (reco!=raiz); System.out.println(); } }

Para borrar el nodo de una determinada posición:

public void borrar (int pos)

Debemos primero identificar si es el primero de la lista (ya que en este caso se modifica el puntero externo raiz):

Page 72: Tutorial Java Ya 3

if (pos <= cantidad ()) { if (pos == 1) {

Si es el primero y el único de la lista hacemos que raiz apunte a null: if (cantidad()==1) { raiz=null;

Si no disponemos un puntero al final de la lista, avanzamos raiz y enlazamos el último nodo con el segundo de la lista: } else { Nodo ultimo=raiz.ant; raiz = raiz.sig; ultimo.sig=raiz; raiz.ant=ultimo; }

En caso que queremos borrar un nodo que se encuentra en medio de la lista o inclusive al final debemos recorrer con un for hasta el nodo que queremos borrar y luego disponemos un puntero en el nodo anterior y otro puntero en el nodo siguiente. Seguidamente procedemos a enlazar los nodos: Nodo reco = raiz; for (int f = 1 ; f <= pos - 1 ; f++) reco = reco.sig; Nodo anterior = reco.ant; reco=reco.sig; anterior.sig=reco; reco.ant=anterior;

50. Recursividad: Conceptos básicos

Primero debemos decir que la recursividad no es una estructura de datos, sino que es una técnica de programación que nos permite que un bloque de instrucciones se ejecute n veces. Remplaza en ocasiones a estructuras repetitivas.

Este concepto será de gran utilidad para el capítulo de la estructura de datos tipo árbol.La recursividad es un concepto difícil de entender en principio, pero luego de analizar diferentes problemas aparecen puntos comunes.

En Java los métodos pueden llamarse a sí mismos. Si dentro de un método existe la llamada a sí mismo decimos que el método es recursivo.Cuando un método se llama a sí mismo, se asigna espacio en la pila para las nuevas variables locales y parámetros.

Al volver de una llamada recursiva, se recuperan de la pila las variables locales y los parámetros antiguos y la ejecución se reanuda en el punto de la llamada al método.

Problema 1:

Page 73: Tutorial Java Ya 3

Implementación de un método recursivo.

Programa:

public class Recursividad {

void repetir() { repetir(); } public static void main(String[] ar) { Recursividad re=new Recursividad(); re.repetir(); }}

La función repetir es recursiva porque dentro de la función se llama a sí misma.Cuando ejecuta este programa se bloqueará y generará una excepción: "Exception in thread "main" java.lang.StackOverflowError"Analicemos como funciona:Primero se ejecuta la función main, luego de crear un objeto llamamos a la función repetir.Hay que tener en cuenta que cada vez que se llama a una función se reservan 4 bytes de la memoria que se liberarán cuando finalice su ejecución.La primera línea de la función llama a la función repetir, es decir que se reservan 4 bytes nuevamente. Se ejecuta nuevamente una instancia de la función repetir y así sucesivamente hasta que la pila estática se colme y se cuelgue el programa.

Problema 2:

Implementación de un método recursivo que reciba un parámetro de tipo entero y luego llame en forma recursiva con el valor del parámetro menos 1.

Programa:

public class Recursividad {

void imprimir(int x) { System.out.println(x); imprimir(x-1); } public static void main(String[] ar) { Recursividad re=new Recursividad(); re.imprimir(5); }}

Desde la main se llama a la función imprimir y se le envía el valor 5. El parámetro x recibe el valor 5. Se ejecuta el algoritmo de la función, imprime el contenido del parámetro (5) y

Page 74: Tutorial Java Ya 3

seguidamente se llama a una función, en este caso a sí misma (por eso decimos que es una función recursiva), enviándole el valor 4.

El parámetro x recibe el valor 4 y se imprime en pantalla el cuatro, llamando nuevamente a la función imprimir enviándole el valor 3.Si continuamos este algoritmo podremos observar que en pantalla se imprime:5 4 3 2 1 0 ?1 ?2 ?3 . . . . . . . . .

hasta que se bloquee el programa.

Tener en cuenta que cada llamada a una función consume 4 bytes por la llamada y en este caso 4 bytes por el parámetro x. Como nunca finaliza la ejecución completa de las funciones se desborda la pila estática por las sucesivas llamadas.

Problema 3:

Implementar un método recursivo que imprima en forma descendente de 5 a 1 de uno en uno.

Programa:

public class Recursividad {

void imprimir(int x) { if (x>0) { System.out.println(x); imprimir(x-1); } } public static void main(String[] ar) { Recursividad re=new Recursividad(); re.imprimir(5); }}

Ahora si podemos ejecutar este programa y observar los resultados en pantalla. Se imprimen los números 5 4 3 2 1 y no se bloquea el programa.Analice qué sucede cada vez que el if (x>0) se evalúa como falso, ¿a qué línea del programa retorna?

Problema 4:

Imprimir los números de 1 a 5 en pantalla utilizando recursividad.

Programa:

public class Recursividad {

Page 75: Tutorial Java Ya 3

void imprimir(int x) { if (x>0) { imprimir(x-1); System.out.println(x); } } public static void main(String[] ar) { Recursividad re=new Recursividad(); re.imprimir(5); }}

Con este ejemplo se presenta una situación donde debe analizarse línea a línea la ejecución del programa y el porque de estos resultados.¿Por qué se imprime en pantalla 1 2 3 4 5 ?Veamos como se apilan las llamadas recursivas:En la primera llamada desde la función main el parámetro x recibe el valor 5.

Cuando llamamos desde la misma función le enviamos el valor de x menos 1 y la memoria queda de la siguiente forma:

Debemos entender que el parámetro x en la nueva llamada está en otra parte de la memoria y que almacena un 4, nosotros le llamaremos x prima.Comienza a ejecutarse la función, la condición del if se valúa como verdadero por lo que entra al bloque y llama recursivamente a la función imprimir pasándole el valor 3 al parámetro.

Nuevamente la condición se valúa como verdadero y llama a la función enviándole un 2, lo mismo ocurre cuando le envía un 1 y un 0.

Page 76: Tutorial Java Ya 3

void imprimir(int x) { if (x>0) { imprimir(x-1); System.out.println(x); } }

Cuando x vale 0 la condición del if se valúa como falsa y sale de la función imprimir.¿Qué línea ahora se ejecuta ?Vuelve a la función main ? NO.Recordemos que la última llamada de la función imprimir se había hecho desde la misma función imprimir por lo que vuelve a la línea: System.out.println(x);

Ahora si analicemos que valor tiene el parámetro x. Observemos la pila de llamadas del gráfico:

x cuarta tiene el valor 1. Por lo que se imprime dicho valor en pantalla.Luego de imprimir el 1 finaliza la ejecución de la función, se libera el espacio ocupado por el parámetro x y pasa a ejecutarse la siguiente línea donde se había llamado la función: System.out.println(x);

Ahora x en esta instancia de la función tiene el valor 2.Así sucesivamente hasta liberar todas las llamadas recursivas.Es importante tener en cuenta que siempre en una función recursiva debe haber un if para finalizar la recursividad ( en caso contrario la función recursiva será infinita y provocará que el programa se bloquee)

Problema 5:

Otro problema típico que se presenta para analizar la recursividad es el obtener el factorial de un número.Recordar que el factorial de un número es el resultado que se obtiene de multiplicar dicho

Page 77: Tutorial Java Ya 3

número por el anterior y así sucesivamente hasta llegar a uno.Ej. el factorial de 4 es 4 * 3 * 2 * 1 es decir 24.

Programa:

public class Recursividad {

int factorial(int fact) { if (fact>0) { int valor=fact * factorial(fact-1); return valor; } else return 1; } public static void main(String[] ar) { Recursividad re=new Recursividad(); int f=re.factorial(4); System.out.println("El factorial de 4 es "+f); }}

La función factorial es recursiva porque desde la misma función llamamos a la función factorial.Debemos hacer el seguimiento del problema para analizar como se calcula.La memoria en la primera llamada:

fact recibe el valor 4 y valor se cargará con el valor que se obtenga con el producto de fact por el valor devuelto por la función factorial (llamada recursiva)

Nuevamente se llama recursivamente hasta que el parámetro fact reciba el valor 0.

Page 78: Tutorial Java Ya 3

Cuando fact recibe un cero la condición del if se valúa como falsa y ejecuta el else retornando un 1, la variable local de la llamada anterior a la función queda de la siguiente manera:

Es importantísimo entender la liberación del espacio de las variables locales y los parámetros en las sucesivas llamadas recursivas.Por último la función main recibe "valor", en este caso el valor 24.

Problema 6:

Implementar un método recursivo para ordenar los elementos de un vector.

Programa:

class Recursivdad { static int [] vec = {312, 614, 88, 22, 54};

void ordenar (int [] v, int cant) { if (cant > 1) { for (int f = 0 ; f < cant - 1 ; f++)

Page 79: Tutorial Java Ya 3

if (v [f] > v [f + 1]) { int aux = v [f]; v [f] = v [f + 1]; v [f + 1] = aux; } ordenar (v, cant - 1); } }

void imprimir () { for (int f = 0 ; f < vec.length ; f++) System.out.print (vec [f] + " "); System.out.println("\n"); }

public static void main (String [] ar) { Recursivdad r = new Recursivdad(); r.imprimir (); r.ordenar (vec, vec.length); r.imprimir (); }}

Hasta ahora hemos visto problemas que se pueden resolver tanto con recursividad como con estructuras repetitivas.

Es muy importante tener en cuenta que siempre que podamos emplear un algoritmo no recursivo será mejor (ocupa menos memoria de ram y se ejecuta más rápidamente)Pero hay casos donde el empleo de recursividad hace mucho más sencillo el algoritmo (tener en cuenta que no es el caso de los tres problemas vistos previamente)

51. Recursividad: Problemas donde conviene aplicar la recursividad

En el concepto anterior se vieron pequeños problemas para entender como funciona la recursividad, pero no se desarrollaron problemas donde conviene utilizar la recursividad.

Problema 1:

Imprimir la información de una lista simplemente encadenada de atrás para adelante.El empleo de estructuras repetitivas para resolver este problema es bastante engorroso y lento (debemos avanzar hasta el último nodo e imprimir, luego avanzar desde el principio hasta el

Page 80: Tutorial Java Ya 3

anteúltimo nodo y así sucesivamente)El empleo de la recursividad para este problema hace más sencillo su solución.

Programa:

public class Recursividad { class Nodo { int info; Nodo sig; } private Nodo raiz; void insertarPrimero(int x) { Nodo nuevo = new Nodo (); nuevo.info = x; nuevo.sig=raiz; raiz=nuevo; }

public void imprimirInversa(Nodo reco) { if (reco!=null) { imprimirInversa(reco.sig); System.out.print(reco.info+"-"); } } public void imprimirInversa () { imprimirInversa(raiz); } public static void main(String[] ar) { Recursividad r=new Recursividad(); r.insertarPrimero (10); r.insertarPrimero(4); r.insertarPrimero(5); r.imprimirInversa(); }}

Page 81: Tutorial Java Ya 3

Cuando llamamos al método recursivo le enviamos raiz y el parámetro reco recibe esta dirección. Si reco es distinto a null llamamos recursivamente al método enviándole la dirección del puntero sig del nodo.Por lo que el parámetro reco recibe la dirección del segundo nodo.

Podemos observar como en las distintas llamadas recursivas el parámetro reco apunta a un nodo. Cuando se van desapilando las llamadas recursivas se imprime primeramente el 10 luego el 4 y por último el 5.

Problema 2:

Recorrer un árbol de directorios en forma recursiva.

Programa:

import java.io.File;public class Recursividad{ public void leer(String inicio,String altura) { File ar=new File(inicio); String[] dir=ar.list(); for(int f=0;f<dir.length;f++){ File ar2=new File(inicio+dir[f]); if (ar2.isFile()) System.out.println(altura+dir[f]); if (ar2.isDirectory()) { System.out.println(altura + "Directorio:"+dir[f].toUpperCase()); leer(inicio+dir[f]+"\\",altura+" "); } }

Page 82: Tutorial Java Ya 3

} public static void main(String[] arguments) { Recursividad rec=new Recursividad(); rec.leer("d:\\windows\\",""); }}

Para recorrer y visitar todos los directorios y archivos de un directorio debemos implementar un algoritmo recursivo que reciba como parámetro el directorio inicial donde comenzaremos a recorrer: public void leer(String inicio,String altura)

Creamos un objeto de la clase File con el directorio que llega como parámetro y mediante el método list obtenemos todos los archivos y directorios de dicho directorio: File ar=new File(inicio); String[] dir=ar.list();

Mediante un for recorremos todo el vector que contiene la lista de archivos y directorios: for(int f=0;f<dir.length;f++){

Creamos un objeto de la clase File para cada directorio y archivo: File ar2=new File(inicio+dir[f]);

Luego de crear un objeto de la clase file podemos verificar si se trata de un archivo o directorio: if (ar2.isFile()) System.out.println(altura+dir[f]); if (ar2.isDirectory()) { System.out.println(altura + "Directorio:"+dir[f].toUpperCase()); leer(inicio+dir[f]+"\\",altura+" "); }

Si es un archivo lo mostramos y si es un directorio además de mostrarlo llamamos recursivamente al método leer con el directorios nuevo a procesar.

Problema 3:

Desarrollar un programa que permita recorrer un laberinto e indique si tiene salida o no.Para resolver este problema al laberinto lo representaremos con una matriz de 10 x 10 JLabel.El valor:"0" Representa pasillo"1" Representa pared"9" Persona"s" Salida

A la salida ubicarla en la componente de la fila 9 y columna 9 de la matriz. La persona comienza a recorrer el laberinto en la fila 0 y columna 0. Los ceros y unos disponerlos en forma aleatoria (con la función random)

Programa:

import javax.swing.*;

Page 83: Tutorial Java Ya 3

import java.awt.*;import java.awt.event.*;class Laberinto extends JFrame implements ActionListener { JLabel[][] l; JButton b1; JButton b2; boolean salida; Laberinto() { setLayout(null); l=new JLabel[10][10]; for(int f=0;f<10;f++) { for(int c=0;c<10;c++) { l[f][c]=new JLabel(); l[f][c].setBounds(20+c*20,50+f*20,20,20); add(l[f][c]); } } b1=new JButton("Recorrer"); b1.setBounds(10,300,100,25); add(b1); b1.addActionListener(this); b2=new JButton("Crear"); b2.setBounds(120,300,100,25); add(b2); b2.addActionListener(this); crear(); } public void crear() { for(int f=0;f<10;f++) { for(int c=0;c<10;c++) { int a=(int)(Math.random()*4); l[f][c].setForeground(Color.black); if (a==0) l[f][c].setText("1"); else l[f][c].setText("0"); } } l[9][9].setText("s");

Page 84: Tutorial Java Ya 3

l[0][0].setText("0"); } public void recorrer(int fil,int col) { if (fil>=0 && fil<10 && col>=0 && col<10 && salida==false) { if (l[fil][col].getText().equals("s")) salida=true; else if (l[fil][col].getText().equals("0")) { l[fil][col].setText("9"); l[fil][col].setForeground(Color.red); recorrer(fil,col+1); recorrer(fil+1,col); recorrer(fil-1,col); recorrer(fil,col-1); } } } public void actionPerformed(ActionEvent e) { if (e.getSource()==b1) { salida=false; recorrer(0,0); if (salida) setTitle("tiene salida"); else setTitle("no tiene salida"); } if (e.getSource()==b2) crear(); } public static void main(String[] ar) { Laberinto l=new Laberinto(); l.setBounds(0,0,300,400); l.setVisible(true); }}

Page 85: Tutorial Java Ya 3

El método más importante es el recorrer: public void recorrer(int fil,int col)

Primero verificamos si la coordenada a procesar del laberinto se encuentra dentro de los límites correctos y además no hayamos encontrado la salida hasta el momento: if (fil>=0 && fil<10 && col>=0 && col<10 && salida==false)

Si entra al if anterior verificamos si estamos en la salida: if (l[fil][col].getText().equals("s")) salida=true;

En el caso que no estemos en la salida verificamos si estamos en pasillo: if (l[fil][col].getText().equals("0")) {

En caso de estar en el pasillo procedemos a fijar dicha JLabel con el caracter "9" e intentamos desplazarnos en las cuatro direcciones (arriba, abajo, derecha e izquierda), este desplazamiento lo logramos llamando recursivamente: l[fil][col].setText("9"); l[fil][col].setForeground(Color.red); recorrer(fil,col+1); recorrer(fil+1,col); recorrer(fil-1,col); recorrer(fil,col-1);

Problemas propuestos

1. Desarrollar el juego del Buscaminas. Definir una matriz de 10*10 de JButton y disponer una 'b' para las bombas (10 diez) un cero en los botones que no tienen bombas en su perímetro, un 1 si tiene una bomba en su perímetro y así sucesivamente. Cuando se presiona un botón si hay un cero proceder en forma recursiva a destapar los botones que se encuentran a sus lados. Disponer el mismo color de frente y fondo de los botones para que el jugador no pueda ver si hay bombas o no.

Solución

import javax.swing.*;import java.awt.*;import java.awt.event.*;class Buscaminas extends JFrame implements ActionListener{ JButton [] [] bot; JButton b1; Buscaminas () { setLayout (null); bot = new JButton [10] [10]; for (int f = 0 ; f < 10 ; f++) { for (int c = 0 ; c < 10 ; c++) { bot [f] [c] = new JButton ("0"); bot [f] [c].setBounds (20 + c * 41, 50 + f * 41, 41, 41);

Page 86: Tutorial Java Ya 3

bot [f] [c].setBackground (Color.lightGray); bot [f] [c].setForeground (Color.lightGray); bot [f] [c].addActionListener (this); add (bot [f] [c]); } } b1 = new JButton ("Reiniciar"); b1.setBounds (20, 470, 100, 30); add (b1); b1.addActionListener (this); disponerBombas (); contarBombasPerimetro (); }

void disponerBombas () { int cantidad = 10; do { int fila = (int) (Math.random () * 10); int columna = (int) (Math.random () * 10); if (bot [fila] [columna].getText ().equals ("b") == false) { bot [fila] [columna].setText ("b"); cantidad--; } } while (cantidad != 0); }

void contarBombasPerimetro () { for (int f = 0 ; f < 10 ; f++) { for (int c = 0 ; c < 10 ; c++) { if (bot [f] [c].getText ().equals ("0") == true) { int cant = contarCoordenada (f, c); bot [f] [c].setText (String.valueOf (cant)); } } } }

int contarCoordenada (int fila, int columna) {

Page 87: Tutorial Java Ya 3

int total = 0; if (fila - 1 >= 0 && columna - 1 >= 0) { if (bot [fila - 1] [columna - 1].getText ().equals ("b") == true) total++; } if (fila - 1 >= 0) { if (bot [fila - 1] [columna].getText ().equals ("b") == true) total++; } if (fila - 1 >= 0 && columna + 1 < 10) { if (bot [fila - 1] [columna + 1].getText ().equals ("b") == true) total++; } if (columna + 1 < 10) { if (bot [fila] [columna + 1].getText ().equals ("b") == true) total++; } if (fila + 1 < 10 && columna + 1 < 10) { if (bot [fila + 1] [columna + 1].getText ().equals ("b") == true) total++; } if (fila + 1 < 10) { if (bot [fila + 1] [columna].getText ().equals ("b") == true) total++; } if (fila + 1 < 10 && columna - 1 >= 0) { if (bot [fila + 1] [columna - 1].getText ().equals ("b") == true) total++; } if (columna - 1 >= 0) { if (bot [fila] [columna - 1].getText ().equals ("b") == true) total++;

Page 88: Tutorial Java Ya 3

} return total;

}

void desactivarJuego () { for (int f = 0 ; f < 10 ; f++) { for (int c = 0 ; c < 10 ; c++) { bot [f] [c].setEnabled (false); } } }

void reiniciar () { setTitle (""); for (int f = 0 ; f < 10 ; f++) { for (int c = 0 ; c < 10 ; c++) { bot [f] [c].setText ("0"); bot [f] [c].setEnabled (true); bot [f] [c].setBackground (Color.lightGray); bot [f] [c].setForeground (Color.lightGray); } } disponerBombas (); contarBombasPerimetro (); }

public void actionPerformed (ActionEvent e) { if (e.getSource () == b1) { reiniciar (); } for (int f = 0 ; f < 10 ; f++) { for (int c = 0 ; c < 10 ; c++) { if (e.getSource () == bot [f] [c]) { if (bot [f] [c].getText ().equals ("b") == true) {

Page 89: Tutorial Java Ya 3

setTitle ("Boooooooooooooomm"); desactivarJuego (); } else if (bot [f] [c].getText ().equals ("0") == true) { recorrer (f, c); } else if (bot [f] [c].getText ().equals ("1") == true || bot [f] [c].getText ().equals ("2") == true || bot [f] [c].getText ().equals ("3") == true || bot [f] [c].getText ().equals ("4") == true || bot [f] [c].getText ().equals ("5") == true || bot [f] [c].getText ().equals ("6") == true || bot [f] [c].getText ().equals ("7") == true || bot [f] [c].getText ().equals ("8") == true) { bot [f] [c].setBackground (Color.yellow); bot [f] [c].setForeground (Color.black); } } } } verificarTriunfo (); }

void verificarTriunfo () { int cant = 0; for (int f = 0 ; f < 10 ; f++) { for (int c = 0 ; c < 10 ; c++) { Color col = bot [f] [c].getBackground (); if (col == Color.yellow) cant++; } } if (cant == 90) { setTitle ("Ganooooooooo"); desactivarJuego (); } }

void recorrer (int fil, int col) {

Page 90: Tutorial Java Ya 3

if (fil >= 0 && fil < 10 && col >= 0 && col < 10) { if (bot [fil] [col].getText ().equals ("0")) { bot [fil] [col].setText (" "); bot [fil] [col].setBackground (Color.yellow); recorrer (fil, col + 1); recorrer (fil, col - 1); recorrer (fil + 1, col); recorrer (fil - 1, col); recorrer (fil - 1, col - 1); recorrer (fil - 1, col + 1); recorrer (fil + 1, col + 1); recorrer (fil + 1, col - 1); } else if (bot [fil] [col].getText ().equals ("1") == true || bot [fil] [col].getText ().equals ("2") == true || bot [fil] [col].getText ().equals ("3") == true || bot [fil] [col].getText ().equals ("4") == true || bot [fil] [col].getText ().equals ("5") == true || bot [fil] [col].getText ().equals ("6") == true || bot [fil] [col].getText ().equals ("7") == true || bot [fil] [col].getText ().equals ("8") == true) { bot [fil] [col].setBackground (Color.yellow); bot [fil] [col].setForeground (Color.black); } } }

public static void main (String [] ar) { Buscaminas m = new Buscaminas (); m.setBounds (0, 0, 470, 600); m.setVisible(true); }}

52. Estructuras dinámicas: Conceptos de árboles

Igual que la lista, el árbol es una estructura de datos. Son muy eficientes para la búsqueda de información. Los árboles soportan estructuras no lineales.

Page 91: Tutorial Java Ya 3

Algunos conceptos de la estructura de datos tipo árbol:

Nodo hoja: Es un nodo sin descendientes (Nodo terminal)Ej. Nodos E ? F ? C y D.

Nodo interior: Es un nodo que no es hoja.Ej. Nodos A y B.

Nivel de un árbol: El nodo A está en el nivel 1 sus descendientes directos están en el nivel 2 y así sucesivamente.

El nivel del árbol está dado por el nodo de máximo nivel.Ej. Este árbol es de nivel 3.

Grado de un nodo: es el número de nodos hijos que tiene dicho nodo (solo se tiene en cuenta los nodos interiores)Ej. El nodo A tiene grado 3.

El nodo B tiene grado 2.Los otros nodos no tienen grado porque no tienen descendientes.

Grado de un árbol: Es el máximo de los grados de todos los nodos de un árbol.Ej. El grado del árbol es 3.

Longitud de camino del nodo x: Al número de arcos que deben ser recorridos para llegar a un nodo x, partiendo de la raiz.La raiz tiene longitud de camino 1, sus descendientes directos tienen longitud de camino 2, etc. En forma general un nodo en el nivel i tiene longitud de camino i.Árbol binario: Un árbol es binario si cada nodo tiene como máximo 2 descendientes.

Page 92: Tutorial Java Ya 3

Para cada nodo está definido el subárbol izquierdo y el derecho.Para el nodo A el subárbol izquierdo está constituido por los nodos B, D y E. Y el subárbol derecho está formado por los nodos C y F.

Lo mismo para el nodo B tiene el subárbol izquierdo con un nodo (D) y un nodo en el subárbol derecho (E).

El nodo D tiene ambos subárboles vacíos.

El nodo C tiene el subárbol izquierdo vacío y el subárbol derecho con un nodo (F).

Árbol binario perfectamente equilibrado: Si para cada nodo el número de nodos en el subárbol izquierdo y el número de nodos en el subárbol derecho, difiere como mucho en una unidad.

Hay que tener en cuenta todos los nodos del árbol.

El árbol de más arriba es perfectamente equilibrado.Ej. árbol que no es perfectamente equilibrado:

El nodo A tiene 3 nodos en el subárbol izquierdo y solo uno en el subárbol derecho, por lo que no es perfectamente equilibrado.

Page 93: Tutorial Java Ya 3

Árbol binario completo: Es un árbol binario con hojas como máximo en los niveles n-1 y n (Siendo n el nivel del árbol)

Los dos árboles graficados son completos porque son árboles de nivel 3 y hay nodos hoja en el nivel 3 en el primer caso, y hay nodos hoja en los niveles 3 y 2 en el segundo caso.Ej. Árbol binario no completo:

Hay nodos hoja en los niveles 4, 3 y 2. No debería haber nodos hojas en el nivel 2.

Page 94: Tutorial Java Ya 3

Árbol binario ordenado: Si para cada nodo del árbol, los nodos ubicados a la izquierda son inferiores al que consideramos raíz para ese momento y los nodos ubicados a la derecha son mayores que la raíz.

Ej. Analicemos si se trata de un árbol binario ordenado:

Para el nodo que tiene el 50:

Los nodos del subárbol izquierdo son todos menores a 50? 8, 25, 30 Si

Los nodos del subárbol derecho son todos mayores a 50? 70 Si.Para el nodo que tiene el 25:

Los nodos del subárbol izquierdo son todos menores a 25? 8 Si

Los nodos del subárbol derecho son todos mayores a 25? 30 Si.No hace falta analizar los nodos hoja. Si todas las respuestas son afirmativas podemos luego decir que se trata de un árbol binario ordenado.

53. Estructuras dinámicas: Inserción de nodos y recorrido de un árbol binario

Para administrar un árbol binario ordenado debemos tener especial cuidado en la inserción.Inicialmente el árbol está vacío, es decir raíz apunta a null:

Insertamos el 400

Page 95: Tutorial Java Ya 3

Insertamos el valor 100. Debemos analizar si raíz es distinto a null verificamos si 100 es mayor o menor a la información del nodo apuntado por raíz, en este caso es menor y como el subárbol izquierdo es null debemos insertarlo allí.

Insertamos el 200. Hay que tener en cuenta que siempre comenzamos las comparaciones a partir de raíz. El 200 es menor que 400, descendemos por el subárbol izquierdo. Luego analizamos y vemos que el 200 es mayor a 100, debemos avanzar por derecha. Como el subárbol derecho es null lo insertamos en dicha posición.

Insertamos el 700 y el árbol será:

Page 96: Tutorial Java Ya 3

Como podemos observar si cada vez que insertamos un nodo respetamos este algoritmo siempre estaremos en presencia de un árbol binario ordenado. Posteriormente veremos el algoritmo en java para la inserción de información en el árbol.

Búsqueda de información en un árbol binario ordenado.

Este es una de los principales usos de los árboles binarios.Para realizar una búsqueda debemos ir comparando la información a buscar y descender por el subárbol izquierdo o derecho según corresponda.Ej. Si en el árbol anterior necesitamos verificar si está almacenado el 700, primero verificamos si la información del nodo apuntado por raíz es 700, en caso negativo verificamos si la información a buscar (700) es mayor a la información de dicho nodo (400) en caso afirmativo descendemos por el subárbol derecho en caso contrario descendemos por el subárbol izquierdo.Este proceso lo repetimos hasta encontrar la información buscada o encontrar un subárbol vacío.

Recorridos de árboles binarios.

Recorrer: Pasar a través del árbol enumerando cada uno de sus nodos una vez.Visitar: Realizar algún procesamiento del nodo.Los árboles pueden ser recorridos en varios órdenes:Pre-orden: - Visitar la raíz. - Recorrer el subárbol izquierdo en pre-orden. - Recorrer el subárbol derecho en pre-orden.

Entre-orden - Recorrer el subárbol izquierdo en entre-orden. - Visitar la raíz. - Recorrer el subárbol derecho en entre-orden.

Post-orden

Page 97: Tutorial Java Ya 3

- Recorrer el subárbol izquierdo en post-orden. - Recorrer el subárbol derecho en post-orden. - Visitar la raíz.

Ejemplo:

Veamos como se imprimen las informaciones de los nodos según su recorrido:Recorrido preorden:

Page 98: Tutorial Java Ya 3

Es decir que el orden de impresión de la información es:400 ? 100 ?50 ? 75 ?200 ? 700

Es importante analizar que el recorrido de árboles es recursivo. Recorrer un subárbol es semejante a recorrer un árbol.

Es buena práctica dibujar el árbol en un papel y hacer el seguimiento del recorrido y las visitas a cada nodo.

Recorrido entreorden:

Page 99: Tutorial Java Ya 3

Es decir que el orden de impresión de la información es:50 ?75 ? 100 ?200 ? 400 ? 700

Si observamos podemos ver que la información aparece ordenada.

Este tipo de recorrido es muy útil cuando queremos procesar la información del árbol en orden.

Recorrido postorden:

Page 100: Tutorial Java Ya 3

Es decir que el orden de impresión de la información es:75 ? 50 ? 200 ? 100 ? 700 ? 400

Page 101: Tutorial Java Ya 3

54. Estructuras dinámicas: Implementación en Java de un árbol binario ordenado

Problema 1:

A continuación desarrollamos una clase para la administración de un árbol binario ordenado.

Programa:

public class ArbolBinarioOrdenado { class Nodo { int info; Nodo izq, der; } Nodo raiz;

public ArbolBinarioOrdenado() { raiz=null; } public void insertar (int info) { Nodo nuevo; nuevo = new Nodo (); nuevo.info = info; nuevo.izq = null; nuevo.der = null; if (raiz == null) raiz = nuevo; else { Nodo anterior = null, reco; reco = raiz; while (reco != null) { anterior = reco; if (info < reco.info) reco = reco.izq; else reco = reco.der; }

Page 102: Tutorial Java Ya 3

if (info < anterior.info) anterior.izq = nuevo; else anterior.der = nuevo; } }

private void imprimirPre (Nodo reco) { if (reco != null) { System.out.print(reco.info + " "); imprimirPre (reco.izq); imprimirPre (reco.der); } }

public void imprimirPre () { imprimirPre (raiz); System.out.println(); }

private void imprimirEntre (Nodo reco) { if (reco != null) { imprimirEntre (reco.izq); System.out.print(reco.info + " "); imprimirEntre (reco.der); } }

public void imprimirEntre () { imprimirEntre (raiz); System.out.println(); }

Page 103: Tutorial Java Ya 3

private void imprimirPost (Nodo reco) { if (reco != null) { imprimirPost (reco.izq); imprimirPost (reco.der); System.out.print(reco.info + " "); } }

public void imprimirPost () { imprimirPost (raiz); System.out.println(); }

public static void main (String [] ar) { ArbolBinarioOrdenado abo = new ArbolBinarioOrdenado (); abo.insertar (100); abo.insertar (50); abo.insertar (25); abo.insertar (75); abo.insertar (150); System.out.println ("Impresion preorden: "); abo.imprimirPre (); System.out.println ("Impresion entreorden: "); abo.imprimirEntre (); System.out.println ("Impresion postorden: "); abo.imprimirPost (); } } public void insertar (int info) { Nodo nuevo; nuevo = new Nodo (); nuevo.info = info; nuevo.izq = null; nuevo.der = null; if (raiz == null)

Page 104: Tutorial Java Ya 3

raiz = nuevo; else { Nodo anterior = null, reco; reco = raiz; while (reco != null) { anterior = reco; if (info < reco.info) reco = reco.izq; else reco = reco.der; } if (info < anterior.info) anterior.izq = nuevo; else anterior.der = nuevo; } }

Creamos un nodo y disponemos los punteros izq y der a null, guardamos la información que llega al método en el nodo.

Si el árbol está vacío, apuntamos raíz al nodo creado; en caso de no estar vacío, dentro de una estructura repetitiva vamos comparando info con la información del nodo, si info es mayor a la del nodo descendemos por el subárbol derecho en caso contrario descendemos por el subárbol izquierdo.

Cuando se encuentra un subárbol vacío insertar el nodo en dicho subárbol. Para esto llevamos un puntero anterior dentro del while. private void imprimirPre (Nodo reco) { if (reco != null) { System.out.print(reco.info + " "); imprimirPre (reco.izq); imprimirPre (reco.der); } }

public void imprimirPre () { imprimirPre (raiz); System.out.println(); }

El método imprimirPre(), es decir el no recursivo se encarga de llamar al método recursivo pasando la dirección del nodo raiz.

Page 105: Tutorial Java Ya 3

El método recursivo void imprimirPre (Nodo reco) lo primero que verifica con un if si reco está apuntando a un nodo (esto es verdad si reco es distinto a null), en caso afirmativo ingresa al bloque del if y realiza: - Visitar la raiz. - Recorrer el subárbol izquierdo en pre-orden. - Recorrer el subárbol derecho en pre-orden.

La visita en este caso es la impresión de la información del nodo y los recorridos son las llamadas recursivas pasando las direcciones de los subárboles izquierdo y derecho.Los algoritmos de los recorridos en entreorden y postorden son similares. La diferencia es que la visita la realizamos entre las llamadas recursivas en el recorrido en entre orden: private void imprimirEntre (Nodo reco) { if (reco != null) { imprimirEntre (reco.izq); System.out.print(reco.info + " "); imprimirEntre (reco.der); } }

y por último en el recorrido en postorden la visita la realizamos luego de las dos llamadas recursivas: private void imprimirPost (Nodo reco) { if (reco != null) { imprimirPost (reco.izq); imprimirPost (reco.der); System.out.print(reco.info + " "); } }

Problema 2:

Confeccionar una clase que permita insertar un entero en un árbol binario ordenado verificando que no se encuentre previamente dicho número.Desarrollar los siguientes métodos:1 - Retornar la cantidad de nodos del árbol.2 - Retornar la cantidad de nodos hoja del árbol.3 - Imprimir en entre orden.4 - Imprimir en entre orden junto al nivel donde se encuentra dicho nodo.5 - Retornar la altura del árbol.6 - Imprimir el mayor valor del árbol.7 - Borrar el nodo menor del árbol.

public class ArbolBinarioOrdenado { class Nodo {

Page 106: Tutorial Java Ya 3

int info; Nodo izq, der; } Nodo raiz; int cant; int altura;

public ArbolBinarioOrdenado() { raiz=null; } public void insertar (int info) { if (!existe(info)) { Nodo nuevo; nuevo = new Nodo (); nuevo.info = info; nuevo.izq = null; nuevo.der = null; if (raiz == null) raiz = nuevo; else { Nodo anterior = null, reco; reco = raiz; while (reco != null) { anterior = reco; if (info < reco.info) reco = reco.izq; else reco = reco.der; } if (info < anterior.info) anterior.izq = nuevo; else anterior.der = nuevo; } } }

public boolean existe(int info) { Nodo reco=raiz; while (reco!=null) { if (info==reco.info)

Page 107: Tutorial Java Ya 3

return true; else if (info>reco.info) reco=reco.der; else reco=reco.izq; } return false; }

private void imprimirEntre (Nodo reco) { if (reco != null) { imprimirEntre (reco.izq); System.out.print(reco.info + " "); imprimirEntre (reco.der); } }

public void imprimirEntre () { imprimirEntre (raiz); System.out.println(); }

private void cantidad(Nodo reco) { if (reco!=null) { cant++; cantidad(reco.izq); cantidad(reco.der); } } public int cantidad() { cant=0; cantidad(raiz); return cant; }

private void cantidadNodosHoja(Nodo reco) { if (reco!=null) { if (reco.izq==null && reco.der==null) cant++;

Page 108: Tutorial Java Ya 3

cantidadNodosHoja(reco.izq); cantidadNodosHoja(reco.der); } } public int cantidadNodosHoja() { cant=0; cantidadNodosHoja(raiz); return cant; }

private void imprimirEntreConNivel (Nodo reco,int nivel) { if (reco != null) { imprimirEntreConNivel (reco.izq,nivel+1); System.out.print(reco.info + " ("+nivel+") - "); imprimirEntreConNivel (reco.der,nivel+1); } }

public void imprimirEntreConNivel () { imprimirEntreConNivel (raiz,1); System.out.println(); } private void retornarAltura (Nodo reco,int nivel) { if (reco != null) { retornarAltura (reco.izq,nivel+1); if (nivel>altura) altura=nivel; retornarAltura (reco.der,nivel+1); } }

public int retornarAltura () { altura=0; retornarAltura (raiz,1); return altura; } public void mayorValorl() {

Page 109: Tutorial Java Ya 3

if (raiz!=null) { Nodo reco=raiz; while (reco.der!=null) reco=reco.der; System.out.println("Mayor valor del árbol:"+reco.info); } } public void borrarMenor() { if (raiz!=null) { if (raiz.izq==null) raiz=raiz.der; else { Nodo atras=raiz; Nodo reco=raiz.izq; while (reco.izq!=null) { atras=reco; reco=reco.izq; } atras.izq=reco.der; } } } public static void main (String [] ar) { ArbolBinarioOrdenado abo = new ArbolBinarioOrdenado (); abo.insertar (100); abo.insertar (50); abo.insertar (25); abo.insertar (75); abo.insertar (150); System.out.println ("Impresion entreorden: "); abo.imprimirEntre (); System.out.println ("Cantidad de nodos del árbol:"+abo.cantidad()); System.out.println ("Cantidad de nodos hoja:"+abo.cantidadNodosHoja()); System.out.println ("Impresion en entre orden junto al nivel del nodo.");

Page 110: Tutorial Java Ya 3

abo.imprimirEntreConNivel(); System.out.print ("Artura del arbol:"); System.out.println(abo.retornarAltura()); abo.mayorValorl(); abo.borrarMenor(); System.out.println("Luego de borrar el menor:"); abo.imprimirEntre (); } }

Para verificar si existe un elemento de información en el árbol disponemos un puntero reco en el nodo apuntado por raiz. Dentro de un while verificamos si la información del parámetro coincide con la información del nodo apuntado por reco, en caso afirmativo salimos del método retornando true, en caso contrario si la información a buscar es mayor a la del nodo procedemos a avanzar reco con la dirección del subárbol derecho: public boolean existe(int info) { Nodo reco=raiz; while (reco!=null) { if (info==reco.info) return true; else if (info>reco.info) reco=reco.der; else reco=reco.izq; } return false; }

Para retornar la cantidad de nodos del árbol procedemos a inicializar un atributo de la clase llamado cant con cero. Llamamos al método recursivo y en cada visita al nodo incrementamos el atributo cant en uno: private void cantidad(Nodo reco) { if (reco!=null) { cant++; cantidad(reco.izq); cantidad(reco.der); } } public int cantidad() { cant=0; cantidad(raiz); return cant; }

Para imprimir todos los nodos en entre orden junto al nivel donde se encuentra planteamos un método recursivo que llegue la referencia del nodo a imprimir junto al nivel de dicho nodo. Desde el método no recursivo pasamos la referencia a raiz y un uno (ya que raiz se encuentra en el

Page 111: Tutorial Java Ya 3

primer nivel)Cada vez que descendemos un nivel le pasamos la referencia del subárbol respectivo junto al nivel que se encuentra dicho nodo: private void imprimirEntreConNivel (Nodo reco,int nivel) { if (reco != null) { imprimirEntreConNivel (reco.izq,nivel+1); System.out.print(reco.info + " ("+nivel+") - "); imprimirEntreConNivel (reco.der,nivel+1); } }

public void imprimirEntreConNivel () { imprimirEntreConNivel (raiz,1); System.out.println(); }

Para obtener la altura del árbol procedemos en el método no recursivo a inicializar el atributo altura con el valor cero. Luego llamamos al método recursivo con la referencia a raiz que se encuentra en el nivel uno. Cada vez que visitamos un nodo procedemos a verificar si el parámetro nivel supera al atributo altura, en dicho caso actualizamos el atributo altura con dicho nivel. private void retornarAltura (Nodo reco,int nivel) { if (reco != null) { retornarAltura (reco.izq,nivel+1); if (nivel>altura) altura=nivel; retornarAltura (reco.der,nivel+1); } }

public int retornarAltura () { altura=0; retornarAltura (raiz,1); return altura; }

Para imprimir el mayor valor del árbol debemos recorrer siempre por derecha hasta encontrar un nodo que almacene null en der: public void mayorValorl() { if (raiz!=null) { Nodo reco=raiz; while (reco.der!=null) reco=reco.der; System.out.println("Mayor valor del árbol:"+reco.info); } }

Para borrar el menor valor del árbol lo primero que comprobamos es si el subárbol izquierdo es nulo luego el menor del árbol es el nodo apuntado por raiz. Luego si el subárbol izquierdo no está vacío procedemos a descender siempre por la izquierda llevando un puntero en el nodo anterior. Cuando llegamos al nodo que debemos borrar procedemos a enlazar el puntero izq del nodo que se encuentra en el nivel anterior con la referencia del subárbol derecho del nodo a borrar:

Page 112: Tutorial Java Ya 3

public void borrarMenor() { if (raiz!=null) { if (raiz.izq==null) raiz=raiz.der; else { Nodo atras=raiz; Nodo reco=raiz.izq; while (reco.izq!=null) { atras=reco; reco=reco.izq; } atras.izq=reco.der; } } }

55. Plug-in WindowBuilder para crear interfaces visuales.

El objetivo de este concepto es conocer el empleo del plug-in WindowBuilder para el desarrollo de interfaces visuales arrastrando componentes.

A partir de la versión 3.7 de Eclipse (Indigo) se incorpora por defecto el plug-in WindowBuilder para la implementación de interfaces visuales.

A medida que uno arrastra componentes visuales sobre un formulario se genera en forma automática el código Java, esto nos permite ser más productivos en el desarrollo de la interfaz de nuestra aplicación y nos ayuda a concentrarnos en la lógica de nuestro problema.

Pasos para crear un JFrame con el WindowBuilder

1 - Creación de un proyecto.

Page 113: Tutorial Java Ya 3

2 - Seleccionamos el nombre de nuestro proyecto (lo llamaremos PruebaWindowBuilder):

Page 114: Tutorial Java Ya 3

3 - Ahora seleccionamos la opción del menú File -> New -> Other ...

Page 115: Tutorial Java Ya 3

4 - Seleccionamos la opción la opción JFrame:

Page 116: Tutorial Java Ya 3

5 - Seguidamente presionamos el botón Next > y definimos el nombre de la clase a crear (Ventana1):

Page 117: Tutorial Java Ya 3

Tenemos en este momento nuestra aplicación mínima generada por el WindowBuilder. Podemos observar que en la parte inferior de la ventana central aparecen dos pestañas (Source y Design) estas dos pestañas nos permiten ver el código fuente de nuestro JFrame en vista de diseño o en vista de código Java:

Page 118: Tutorial Java Ya 3
Page 119: Tutorial Java Ya 3

Luego en vista de "Design":

Page 120: Tutorial Java Ya 3

6 - Configuramos el Layout de JFrame presionando el botón derecho del mouse sobre el formulario generado y seleccionamos la opción SetLayout > Absolute layout (esto nos permite luego disponer controles visuales como JButton, JLabel etc. en posiciones fijas dentro del JFrame):

Page 121: Tutorial Java Ya 3

7 - De la ventana Palette seleccionamos con el mouse un objeto de la clase JButton (presionamos con el mouse dicha componente, deberá aparecer seleccionada) y luego nos desplazamos con el mouse sobre el JFrame y presionamos el botón del mouse nuevamente ( en este momento aparece el botón dentro del JFrame):

En todo momento podemos cambiar la pestaña de "Source" y "Design" para ver el código generado. Por ejemplo cuando agregamos el botón podemos ver que se agregó un objeto de la clase JButton al constructor:

import java.awt.BorderLayout;import java.awt.EventQueue;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JButton;

public class Ventana1 extends JFrame {

private JPanel contentPane;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() {

Page 122: Tutorial Java Ya 3

try { Ventana1 frame = new Ventana1(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Ventana1() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JButton btnNewButton = new JButton("New button"); btnNewButton.setBounds(335, 228, 89, 23); contentPane.add(btnNewButton); }}

Page 123: Tutorial Java Ya 3

Inicializar propiedades de los objetos.

Crear un proyecto y luego un JFrame con las siguientes componentes visuales :Dos controles de tipo JLabel, dos JTextField y dos JButton (previamente definir el layout para el panel contenido en el JFrame de tipo Absolute Layout)

Si hacemos doble clic con el mouse en la pestaña Ventana1.java podemos maximizar el espacio de nuestro editor visual (haciendo nuevamente doble clic vuelve al tamaño anterior)

Seleccionemos el primer JLabel de nuestro formulario y observemos las distintas partes que componen el plug-in WindowBuilder. En la parte superior izquierda se encuentra la sección "Structure" donde se muestran las componentes visuales agregadas al formulario. Aparece resaltada la que se encuentra actualmente seleccionada.

Page 124: Tutorial Java Ya 3

En la parte inferior aparece la ventana de "Properties" o propiedades del control visual

Veamos algunas propiedades que podemos modificar desde esta ventana y los cambios que se producen en el código fuente en java.

La propiedad text cambia el texto que muestra el objeto JLabel. Probemos de disponer el texto "Ingrese nombre de usuario:". De forma similar hagamos los cambios en la propiedad text de los otros controles visuales de nuestro JFrame:

Page 125: Tutorial Java Ya 3

Si ahora seleccionamos la pestaña inferior para ver la vista de código java: "Source" podemos ver que el WindowBuilder nos generó automáticamente el código para inicializar los textos de los controles JLabel y JButton:

import java.awt.BorderLayout;import java.awt.EventQueue;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JLabel;import javax.swing.JTextField;import javax.swing.JButton;

Page 126: Tutorial Java Ya 3

public class Ventana1 extends JFrame {

private JPanel contentPane; private JTextField textField; private JTextField textField_1;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { Ventana1 frame = new Ventana1(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Ventana1() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 203); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JLabel lblNewLabel = new JLabel("Ingrese nombre de usuario:"); lblNewLabel.setBounds(20, 21, 149, 14); contentPane.add(lblNewLabel);

Page 127: Tutorial Java Ya 3

JLabel lblNewLabel_1 = new JLabel("Ingrese clave:"); lblNewLabel_1.setBounds(20, 61, 125, 14); contentPane.add(lblNewLabel_1); textField = new JTextField(); textField.setBounds(179, 18, 225, 20); contentPane.add(textField); textField.setColumns(10); textField_1 = new JTextField(); textField_1.setBounds(179, 58, 225, 20); contentPane.add(textField_1); textField_1.setColumns(10); JButton btnNewButton = new JButton("Aceptar"); btnNewButton.setBounds(178, 89, 89, 23); contentPane.add(btnNewButton); JButton btnNewButton_1 = new JButton("Cancelar"); btnNewButton_1.setBounds(315, 89, 89, 23); contentPane.add(btnNewButton_1); }}

Como podemos observar ahora cuando se crean los objetos de la clase JLabel en el constructor se inicializan con los valores cargados en la propiedad text: JLabel lblNewLabel = new JLabel("Ingrese nombre de usuario:"); ..... JLabel lblNewLabel_1 = new JLabel("Ingrese clave:"); ..... JButton btnNewButton = new JButton("Aceptar"); ..... JButton btnNewButton_1 = new JButton("Cancelar"); .....

Problema propuesto 1

Crear la interfaz visual que aparece abajo. Inicializar las propiedades que corresponde.

Page 128: Tutorial Java Ya 3

Eventos

Para asociar eventos el plug-in WindowBuilder nos proporciona una mecánica para automatizar la generación de las interfaces que capturan los eventos de los objetos JButton, JMenuItem, JList etc.

Crearemos una interfaz visual similar a esta (tres controles de tipo JLabel, dos JTextField y un JButton):

Page 129: Tutorial Java Ya 3

Ahora seleccionamos el control JButton y en la ventana de propiedades presionamos el icono de la parte superior:

Page 130: Tutorial Java Ya 3

Hacemos doble clic sobre la palabra performed y vemos que se abre el editor de texto y aparece el siguiente código generado automáticamente: btnSumar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { } });

En el parámetro del método addActionListener del botón que suma se le pasa la referencia a una interface que se crea de tipo ActionListener e implementa el método actionPerformed donde agregaremos el código necesario para responder el evento.

Para este problema debemos rescatar los valores almacenados en los controles de tipo JTextField, convertirlos a entero, sumarlos y enviar dicho resultado a una JLabel. btnSumar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int v1=Integer.parseInt(textField.getText()); int v2=Integer.parseInt(textField_1.getText()); int suma=v1+v2; lblResultado.setText(String.valueOf(suma)); } });

Cuando compilamos vemos que no tenemos acceso al objeto lblResultado ya que está definido como una variable local al constructor. Si queremos que se definan como atributos de la clase debemos seleccionar la JLabel y presionar "convert Local to Field" (convertir de variable local a atributo de la clase):

Page 131: Tutorial Java Ya 3

Después de esto podemos acceder desde el método actionPerformed a la label.

Problema

Crear un menú de opciones que permita cambiar el color de fondo. Disponer un JMenuBar, un JMenu y 3 objetos de la clase JMenuItem. Asociar los eventos respectivos para cada control de tipo JMenuItem.

La interfaz visual debe quedar similar a la siguiente:

Page 132: Tutorial Java Ya 3

Para crear esta interface debemos primero seleccionar la pestaña "Menu" donde se encuentran las componentes relacionadas a la creación de menúes.

Debemos agregar (en este orden las siguientes componentes):1 - Un JMenuBar en la parte superior.2 - Un objeto de la clase JMenu en la barra del JMenuBar (podemos disponer el texto que queremos que se muestre)3 - Agregamos un objeto de la clase JMenuItem en el sector donde aparece el texto: "Add items here". Los mismos pasos hacemos para agregar los otros dos JMenuItem.

Ahora debemos asociar el evento clic para cado JMenuItem. Seleccionamos primero el control de tipo JMenuItem y en la ventana de "Properties" presionamos el botón "Show events" y generamos el actionPerformed para el JMenuItem seleccionado.

Luego codificamos: mntmRojo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { contentPane.setBackground(Color.red); } });

Page 133: Tutorial Java Ya 3

Para cambiar el color del JFrame en realidad debemos modificar el color del JPanel que cubre el JFrame. El objeto de la clase JPanel llamado contentPane tiene un método llamado setBackground que nos permite fijar el color de fondo.

De forma similar asociamos los eventos para los otros dos objetos de la clase JMenuItem: JMenuItem mntmVerde = new JMenuItem("Verde"); mntmVerde.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { contentPane.setBackground(Color.green); } }); mnNewMenu.add(mntmVerde); JMenuItem mntmAzul = new JMenuItem("Azul"); mntmAzul.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { contentPane.setBackground(Color.blue); } });

56. Plug-in WindowBuilder problemas resueltos

Desarrollaremos una serie de aplicaciones que requieran componentes visuales y utilizaremos el WindowBuilder para agilizar su desarrollo.

Problema 1

Desarrollar un programa que muestre el tablero de un ascensor:

El funcionamiento es el siguiente:Inicialmente el ascensor está en el piso 1.Por ejemplo: si se presiona el botón 3 se muestra en un JLabel el piso número 3 y en otra JLabel la dirección. La cadena "Sube", en caso de presionar un piso superior al actual. Mostramos la

Page 134: Tutorial Java Ya 3

cadena "Baja" en el JLabel si se presiona un piso inferior. y si el piso donde se encuentra actualmente coincide con el presionado luego mostrar el mensaje "Piso actual".

Algunos consejos para crear la interfaz visual:1 - Lo primero que debemos hacer cada vez que creamos un JFrame es definir el Layout a utilizar (normalmente utilizaremos "Absolute Layout", esto lo hacemos presionando el botón derecho del mouse dentro del JFrame y seleccionando la opción "Set Layout".

El tipo de layout a utilizar también se lo puede fijar seleccionando el objeto "contentPane"(este objeto es de la clase JPanel y todo JFrame lo contiene como fondo principal) y luego en la ventana de propiedades cambiamos la propiedad "Layot"

2 - Cuando creamos el primer JButton definimos el nombre del objeto cambiando la propiedad "Variable" y mediante la propiedad Text definimos el texto a mostrar (con el mouse dimensionamos el JButton):

3 - Los otros botones los podemos crear de la misma manera seleccionando un objeto de la clase JButton de la "Palette" o cuando tenemos que crear otros objetos semejantes podemos presionar el botón derecho del mouse sobre el objeto a duplicar y seguidamente en el menú contextual seleccionar la opción "Copy" y seguidamente la opción "Paste" con lo que tendremos otro objeto semejante.

Page 135: Tutorial Java Ya 3

Luego si deberemos definir un nombre para el objeto (propiedad "Variable") y la propiedad "text" para la etiqueta a mostrar:

4 - Los objetos que necesitemos consultar o modificar en tiempo de ejecución debemos definirlos como atributos de clase (también llamados campos de clase)En este problema cuando se presione alguno de los cuatro botones debemos consultar el contendido de la label que indica el piso actual y la label que muestra la dirección será modificada por otro String.

Para definir un control visual como atributo de clase debemos seleccionarlo y presionar en la ventana de propiedades el botón "Convert local to field" (en nuetro problema definamos a estos dos objetos de la clase JLabel con el nombre l1 y l2):

Page 136: Tutorial Java Ya 3

5 - Para capturar el evento clic de un objeto de la clase JButton debemos seleccionarlo y presionar el botón "Show Events":

Page 137: Tutorial Java Ya 3

y seguidamente hacer doble-clic sobre el evento a implementar:

La solución a este problema es el siguiente:

import java.awt.EventQueue;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JButton;import javax.swing.JLabel;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;

Page 138: Tutorial Java Ya 3

public class Ascensor extends JFrame {

private JPanel contentPane; private JLabel l1; private JLabel l2;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { Ascensor frame = new Ascensor(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Ascensor() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null);

JButton b1 = new JButton("1"); b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int pisoactual=Integer.parseInt(l1.getText()); if (1<pisoactual) l2.setText("Baja");

Page 139: Tutorial Java Ya 3

else l2.setText("Piso actual"); l1.setText("1"); } }); b1.setBounds(38, 173, 53, 44); contentPane.add(b1);

JButton b2 = new JButton("2"); b2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int pisoactual=Integer.parseInt(l1.getText()); if (2<pisoactual) l2.setText("Baja"); else if (2>pisoactual) l2.setText("Sube"); else l2.setText("Piso actual"); l1.setText("2"); } }); b2.setBounds(38, 118, 53, 44); contentPane.add(b2);

JButton b3 = new JButton("3"); b3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int pisoactual=Integer.parseInt(l1.getText()); if (3<pisoactual) l2.setText("Baja"); else if (3>pisoactual) l2.setText("Sube"); else l2.setText("Piso actual"); l1.setText("3"); } });

Page 140: Tutorial Java Ya 3

b3.setBounds(38, 63, 53, 44); contentPane.add(b3);

JButton b4 = new JButton("4"); b4.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int pisoactual=Integer.parseInt(l1.getText()); if (4>pisoactual) l2.setText("Sube"); else l2.setText("Piso actual"); l1.setText("4"); } }); b4.setBounds(38, 11, 53, 44); contentPane.add(b4);

JLabel lblNewLabel = new JLabel("piso"); lblNewLabel.setBounds(186, 41, 46, 14); contentPane.add(lblNewLabel);

JLabel lblDireccion = new JLabel("direccion"); lblDireccion.setBounds(186, 93, 61, 14); contentPane.add(lblDireccion);

l1 = new JLabel("1"); l1.setBounds(272, 41, 46, 14); contentPane.add(l1);

l2 = new JLabel("baja"); l2.setBounds(272, 93, 92, 14); contentPane.add(l2); }}

Cuando se presiona el botón 1 procedemos a extraer el contenido de la label 1 que almacena el valor del piso actual, como se presionó el primer botón preguntamos si 1 es menor al piso actual, en dicho caso mostramos en la label 2 el texto "Baja" en caso contrario significa que estamos actualmente en el piso 1 (cuando se presiona el botón 1 nunca puede decir el texto sube) Luego cambiamos la etiqueta de la label 1 con el valor "1" que es el nuevo piso:

Page 141: Tutorial Java Ya 3

b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int pisoactual=Integer.parseInt(l1.getText()); if (1<pisoactual) l2.setText("Baja"); else l2.setText("Piso actual"); l1.setText("1"); } });

El botón 4 es similar al botón 1 ya que mostraremos la etiqueta "Sube" o "Piso actual": b4.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int pisoactual=Integer.parseInt(l1.getText()); if (4>pisoactual) l2.setText("Sube"); else l2.setText("Piso actual"); l1.setText("4"); } });

Si se presiona el botón del segundo piso debemos verificar si 2 es menor, mayor o igual al piso actual (igual para el botón del tercer piso): b2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int pisoactual=Integer.parseInt(l1.getText()); if (2<pisoactual) l2.setText("Baja"); else if (2>pisoactual) l2.setText("Sube"); else l2.setText("Piso actual"); l1.setText("2"); } });

Problema 2

Desarrollar un programa que muestre un panel para extracción de una bebida:

Page 142: Tutorial Java Ya 3

Por un lado disponer tres objetos de la clase JRadioButton (llamarlos radio1, radio2 y radio 3), configurar el primero para que aparezca seleccionado (propiedad "selected")

Disponer dos objetos de la clase JComboBox (llamarlos comboPesos y comboCentavos)

En el JComboBox pesos inicializar la propiedad model con los valores del 0 al 5 (hay que cargar un valor por cada línea en el diálogo que aparece)

En forma similar el segundo JComboBox cargamos los valores: 0,10,20,30 etc. hasta 90.Se sabe que :

Bebida A tiene un costo de 0 pesos 80 centavos.Bebida B tiene un costo de 1 peso 20 centavos.Bebida C tiene un costo de 3 pesos 10 centavos.

Cuando se presiona el botón extraer mostrar en la label de resultado el texto "Correcto" o "Incorrecto" dependiendo la bebida seleccionada y la cantidad de pesos y centavos seleccionados.Solución:

Para que todos los JRadioButton estén asociados (es decir que cuando se seleccione uno se deseleccione el actual lo debemos hacer en forma visual), primero seleccionamos con el mouse todos los JRadioButton (para seleccionar varios controles presionamos la tecla "Ctrl" del teclado y con el boton izquierdo del mouse seleccionamos los tres JRadioButton ) y seguidamente presionamos el botón derecho del mouse y seleccionamos "New standard":

Page 143: Tutorial Java Ya 3

Ahora ya tenemos los tres controles de tipo JRadioButton agrupados.El código fuente del problema es:

import java.awt.EventQueue;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JRadioButton;import javax.swing.JLabel;import javax.swing.JComboBox;import javax.swing.DefaultComboBoxModel;import javax.swing.JButton;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;

Page 144: Tutorial Java Ya 3

import javax.swing.ButtonGroup;

public class PanelBebidas extends JFrame {

private JPanel contentPane; private JComboBox comboPesos; private JComboBox comboCentavos; private JRadioButton radio1; private JRadioButton radio2; private JRadioButton radio3; private JLabel l1; private final ButtonGroup buttonGroup = new ButtonGroup();

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { PanelBebidas frame = new PanelBebidas(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public PanelBebidas() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 600, 319); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

Page 145: Tutorial Java Ya 3

setContentPane(contentPane); contentPane.setLayout(null); JLabel lblNewLabel = new JLabel("Pesos"); lblNewLabel.setBounds(263, 59, 46, 14); contentPane.add(lblNewLabel); comboPesos = new JComboBox(); comboPesos.setModel(new DefaultComboBoxModel(new String[] {"0", "1", "2", "3", "4", "5"})); comboPesos.setBounds(319, 56, 73, 20); contentPane.add(comboPesos); JLabel lblNewLabel_1 = new JLabel("Centavos"); lblNewLabel_1.setBounds(263, 102, 58, 14); contentPane.add(lblNewLabel_1); comboCentavos = new JComboBox(); comboCentavos.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { } }); comboCentavos.setModel(new DefaultComboBoxModel(new String[] {"0", "10", "20", "30", "40", "50", "60", "70", "80", "90"})); comboCentavos.setBounds(319, 96, 73, 20); contentPane.add(comboCentavos); JButton b1 = new JButton("Extraer"); b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { int pesos=Integer.parseInt((String)comboPesos.getSelectedItem()); int centavos=Integer.parseInt((String)comboCentavos.getSelectedItem()); if (radio1.isSelected() && pesos==0 && centavos==80)

Page 146: Tutorial Java Ya 3

l1.setText("Correcto"); else if (radio2.isSelected() && pesos==1 && centavos==20) l1.setText("Correcto"); else if (radio3.isSelected() && pesos==3 && centavos==10) l1.setText("Correcto"); else l1.setText("Incorrecto"); } }); b1.setBounds(30, 196, 89, 23); contentPane.add(b1); l1 = new JLabel("resultado"); l1.setBounds(148, 205, 73, 14); contentPane.add(l1); radio1 = new JRadioButton("Bebida A"); buttonGroup.add(radio1); radio1.setSelected(true); radio1.setBounds(10, 55, 109, 23); contentPane.add(radio1); radio2 = new JRadioButton("Bebida B"); buttonGroup.add(radio2); radio2.setBounds(10, 81, 109, 23); contentPane.add(radio2); radio3 = new JRadioButton("Bebida C"); buttonGroup.add(radio3); radio3.setBounds(10, 107, 109, 23); contentPane.add(radio3); }}

Page 147: Tutorial Java Ya 3

La lógica del problema se encuentra cuando se presiona el botón "Extraer":

b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { int pesos=Integer.parseInt((String)comboPesos.getSelectedItem()); int centavos=Integer.parseInt((String)comboCentavos.getSelectedItem()); if (radio1.isSelected() && pesos==0 && centavos==80) l1.setText("Correcto"); else if (radio2.isSelected() && pesos==1 && centavos==20) l1.setText("Correcto"); else if (radio3.isSelected() && pesos==3 && centavos==10) l1.setText("Correcto"); else l1.setText("Incorrecto"); } });

Extraemos los contenidos de los dos controles de tipo JComboBox y los convertimos a entero. Luego mediante tres if verificamos si el primer JRadioButton está seleccionado y el dinero seleccionado corresponde a exactamente 0 pesos y 80 centavos, en tal caso mostramos en la label el mensaje "Correcto". La lógica es similar para las otras dos bebidas.

Problema 3

Un embalse debe manejar la cantidad de mts3 de agua que pasa por cada compuerta. Por cada compuerta puede pasar un caudal de 100 mts3 x seg.

Cuando presionamos el botón "Actualizar caudal" mostramos el nivel de caudal actual y un mensaje que indica si el caudal es Bajo (0 a 100 mts3 x seg.) , Medio (> 100 -200 mts3. x seg.) o Alto (>200 mts3 x seg.)

Para la selección del caudal de cada compuerta utilizar componentes de tipo JSpinner.

Page 148: Tutorial Java Ya 3

El código fuente es:

import java.awt.EventQueue;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JSpinner;import javax.swing.JLabel;import javax.swing.JButton;import javax.swing.SpinnerNumberModel;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;

public class Embalse extends JFrame {

private JPanel contentPane; private JSpinner spinner1; private JSpinner spinner2; private JSpinner spinner3; private JLabel l1;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() {

Page 149: Tutorial Java Ya 3

public void run() { try { Embalse frame = new Embalse(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Embalse() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); spinner1 = new JSpinner(); spinner1.setModel(new SpinnerNumberModel(0, 0, 100, 1)); spinner1.setBounds(31, 35, 62, 20); contentPane.add(spinner1); spinner2 = new JSpinner(); spinner2.setModel(new SpinnerNumberModel(0, 0, 100, 1)); spinner2.setBounds(31, 85, 62, 20); contentPane.add(spinner2); spinner3 = new JSpinner(); spinner3.setModel(new SpinnerNumberModel(0, 0, 100, 1)); spinner3.setBounds(31, 134, 62, 20); contentPane.add(spinner3); JLabel lblCompuerta = new JLabel("compuerta 1");

Page 150: Tutorial Java Ya 3

lblCompuerta.setBounds(106, 38, 82, 14); contentPane.add(lblCompuerta); JLabel lblCompuerta_1 = new JLabel("compuerta 2"); lblCompuerta_1.setBounds(106, 88, 82, 14); contentPane.add(lblCompuerta_1); JLabel lblCompuerta_2 = new JLabel("compuerta 3"); lblCompuerta_2.setBounds(106, 137, 82, 14); contentPane.add(lblCompuerta_2); JButton btnNewButton = new JButton("Actualizar caudal"); btnNewButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { int v1=Integer.parseInt(spinner1.getValue().toString()); int v2=Integer.parseInt(spinner2.getValue().toString()); int v3=Integer.parseInt(spinner3.getValue().toString()); int suma=v1+v2+v3; if (suma<=100) l1.setText("Bajo"); else if (suma<=200) l1.setText("Medio"); else l1.setText("Alto"); } }); btnNewButton.setBounds(31, 198, 157, 23); contentPane.add(btnNewButton); l1 = new JLabel("resultado"); l1.setBounds(218, 203, 149, 14); contentPane.add(l1); }}

En el evento clic del JButton extraemos los tres valores almacenados en los JSPinner:

Page 151: Tutorial Java Ya 3

int v1=Integer.parseInt(spinner1.getValue().toString()); int v2=Integer.parseInt(spinner2.getValue().toString()); int v3=Integer.parseInt(spinner3.getValue().toString());

y mediante tres if valuamos si la suma es menor o igual a 100 o menor o igual a 200 o en su defecto es mayor a 200: int suma=v1+v2+v3; if (suma<=100) l1.setText("Bajo"); else if (suma<=200) l1.setText("Medio"); else l1.setText("Alto");

Problema propuesto1. Implementar un programa para la extracción de dinero de un cajero automático.

Se debe poder fijar la cantidad de dinero a extraer:Disponer un control de tipo JComboBox (disponer los valores: 0,50,150 etc. hasta 500)Por otro lado poder seleccionar el tipo de cuenta (almacenar en otro JComboBox los textos "Caja de Ahorro" y "Cuenta Corriente".Se debe tener en cuenta que:De Caja de Ahorro se puede extraer hasta 200.De Cuenta Corriente se puede extraer hasta 400.Al presionar el botón extraer mostrar en una label el texto "correcto" si para el tipo de cuenta el importe está permitido.Inicialmente el cajero tiene almacenado un monto de 3000 pesos. Restar en cada extracción el monto respectivo y mostrar el mensaje ?fuera de servicio? cuando se intenta extraer más del dinero que hay en el cajero.

Page 152: Tutorial Java Ya 3

57. Clase Graphics y sus métodosJava proporciona la clase Graphics, que permite dibujar elipses, cuadrados, líneas, mostrar texto y también tiene muchos otros métodos de dibujo. Para cualquier programador, es esencial el entendimiento de la clase Graphics, antes de adentrarse en el dibujo en Java.

La clase Graphics proporciona el entorno de trabajo para cualquier operación gráfica que se realice dentro del AWT.

Para poder pintar, un programa necesita un contexto gráfico válido, representado por una instancia de la clase Graphics. Pero esta clase no se puede instanciar directamente; así que debemos crear un componente y pasarlo al programa como un argumento al método paint().

El único argumento del método paint() es un objeto de esta clase. La clase Graphics dispone de métodos para soportar tres categorías de operaciones gráficas:1) Dibujo de primitivas gráficas,2) Dibujo de texto,3) Presentación de imágenes en formatos *.gif y *.jpeg.

Además, la clase Graphics mantiene un contexto gráfico: un área de dibujo actual, un color de dibujo del Background y otro del Foreground, un Font con todas sus propiedades, etc.Los ejes están situados en la esquina superior izquierda. Las coordenadas se miden siempre en pixels.

Problema 1

Crear una aplicación que utilice las primitivas gráficas principales que provee la clase Graphics:

Page 153: Tutorial Java Ya 3

import java.awt.BorderLayout;import java.awt.Color;import java.awt.EventQueue;import java.awt.Graphics;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;

public class Grafico1 extends JFrame {

private JPanel contentPane;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { Grafico1 frame = new Grafico1(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Grafico1() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null);

Page 154: Tutorial Java Ya 3

setBounds(0,0,800,600); } public void paint (Graphics g) { super.paint(g);

g.setColor (Color.blue); g.drawLine (0, 70, 100, 70); g.drawRect (150, 70, 50, 70); g.drawRoundRect (250, 70, 50, 70, 6, 6); g.drawOval (350, 70, 50, 70); int [] vx1 = {500, 550, 450}; int [] vy1 = {70, 120, 120}; g.drawPolygon (vx1, vy1, 3);

g.setColor (Color.red); g.fillRect (150, 270, 50, 70); g.fillRoundRect (250, 270, 50, 70, 6, 6); g.fillOval (350, 270, 50, 70); int [] vx2 = {500, 550, 450}; int [] vy2 = {270, 320, 320}; g.fillPolygon (vx2, vy2, 3); }}

Sobreescribimos el método paint heredado de la clase JFrame: public void paint (Graphics g) {

El método paint se ejecuta cada vez que el JFrame debe ser redibujado y llega como parámetro un objeto de la clase Graphics. Este objeto nos permite acceder al fondo del JFrame y utilizando las primitivas gráficas dibujar líneas, rectángulos, elipses etc.

Lo primero que hacemos dentro de este método es llamar al método paint de la clase superior para que se pinte el fondo del JFrame y otras componentes contenidas dentro (para llamar al método paint de la clase JFrame debemos anteceder la palabra clave super y pasar el parámetro respectivo): super.paint(g);

Mediante el método setColor activamos un color: g.setColor (Color.blue);

Dibuja una línea desde la coordenada (0,70) es decir columna 0 y fila 70 en píxeles, hasta la coordenada (100,70). La línea es de color azul:

Page 155: Tutorial Java Ya 3

g.drawLine (0, 70, 100, 70);Dibujamos un rectángulo desde la coordenada (150,70) con un ancho de 50 píxeles y un alto de 70, solo se pinta el perímetro del rectángulo de color azul): g.drawRect (150, 70, 50, 70);

Similar a drawRect más un valor de redondeo de los vertices que le indicamos en el quinto y sexto parámetro: g.drawRoundRect (250, 70, 50, 70, 6, 6);

Dibujamos un óvalo: g.drawOval (350, 70, 50, 70);

Dibujamos un triángulo (debemos indicar mediante dos vectores los vértices de cada punto del triángulo), el primer punto es el (500,70) el segundo punto es el (550,120) y por último el punto (450,120): int [] vx1 = {500, 550, 450}; int [] vy1 = {70, 120, 120}; g.drawPolygon (vx1, vy1, 3);

De forma similar los métodos fillRect, fillRoundRect, fillOval y fillPolygon son similares a los anteriores con la diferencia que pinta su interior con el color activo de la última llamada al método setColor: g.setColor (Color.red); g.fillRect (150, 270, 50, 70); g.fillRoundRect (250, 270, 50, 70, 6, 6); g.fillOval (350, 270, 50, 70); int [] vx2 = {500, 550, 450}; int [] vy2 = {270, 320, 320}; g.fillPolygon (vx2, vy2, 3);

Dibujar texto

La clase Graphics permite ?dibujar? texto, como alternativa al texto mostrado en los componentes JLabel, JTextField y JTextArea. El método que permite graficar texto sobre el JFrame es:drawString(String str, int x, int y);

Problema 2. Crear una aplicación que utilice las primitiva drawString de Java:

import java.awt.BorderLayout;import java.awt.Color;import java.awt.EventQueue;import java.awt.Graphics;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;

public class Grafico1 extends JFrame {

private JPanel contentPane;

Page 156: Tutorial Java Ya 3

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { Grafico1 frame = new Grafico1(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Grafico1() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setLayout(new BorderLayout(0, 0)); setContentPane(contentPane); setBounds(0,0,800,600); }

public void paint (Graphics g) { super.paint(g); g.setColor (Color.blue); g.drawString("Primer linea",10,200); g.drawString("Segunda linea",10,300); } }

Page 157: Tutorial Java Ya 3

Clase Color

La clase java.awt.Color encapsula colores utilizando el formato RGB (Red, Green, Blue). Las componentes de cada color primario en el color resultante se expresan con números enteros entre 0 y 255, siendo 0 la intensidad mínima de ese color y 255 la máxima. En la clase Color existen constantes para colores predeterminados de uso frecuente: black, white, green, blue, red, yellow, magenta, cyan, orange, pink, gray, darkGray, lightGray.

Problema 3

Crear una aplicación que dibuje 255 líneas creando un color distinto para cada una de ellas:

import java.awt.BorderLayout;import java.awt.Color;import java.awt.EventQueue;import java.awt.Graphics;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;

public class Grafico1 extends JFrame {

private JPanel contentPane;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() {

Page 158: Tutorial Java Ya 3

try { Grafico1 frame = new Grafico1(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Grafico1() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setLayout(new BorderLayout(0, 0)); setContentPane(contentPane); setBounds(0,0,800,255); } public void paint (Graphics g) { super.paint(g); int fila = 0; for (int rojo = 0 ; rojo <= 255 ; rojo++) { Color col = new Color (rojo, 0, 0); g.setColor (col); g.drawLine (0, fila, 800, fila); fila++; } }

}Dentro de un for creamos objetos de la clase Color y fijamos el color de la línea seguidamente (con esto logramos un degradé del negro al rojo): int fila = 0; for (int rojo = 0 ; rojo <= 255 ; rojo++)

Page 159: Tutorial Java Ya 3

{ Color col = new Color (rojo, 0, 0); g.setColor (col); g.drawLine (0, fila, 800, fila); fila++; }

Presentación de imágenes

Java permite incorporar imágenes de tipo GIF y JPEG definidas en ficheros. Se dispone para ello de la clase java.awt.Image. Para cargar una imagen hay que indicar la localización del archivo y cargarlo mediante el método getImage(). Este método existe en las clases java.awt.Toolkit.

Entonces, para cargar una imagen hay que comenzar creando un objeto (o una referencia) Image y llamar al método getImage() (de Toolkit); Una vez cargada la imagen, hay que representarla, para lo cual se redefine el método paint() para llamar al método drawImage() de la clase Graphics. Los objetos Graphics pueden mostrar imágenes a través del método: drawImage(). Dicho método admite varias formas, aunque casi siempre hay que incluir el nombre del objeto imagen creado.

Clase Image

Una imagen es un objeto gráfico rectangular compuesto por pixels coloreados. Cada pixel en una imagen describe un color de una particular localización de la imagen.

A continuación, algunos métodos de la clase Image:

La clase Graphics provee el método drawImage() para dibujar imagenes; este método admite varias formas:- drawImage (Image i, int x, int y, ImageObserver o)- drawImage (Image i,int x,int y,int width,int height,ImageObserver o)

Problema 4

Crear una aplicación que muestre un archivo jpg dentro de un JFrame.

Page 160: Tutorial Java Ya 3

Luego de crear el proyecto debemos disponer un archivo en la carpeta raiz del proyecto (el archivo debe llamarse imagen1.jpg)

import java.awt.BorderLayout;import java.awt.EventQueue;import java.awt.Graphics;import java.awt.Image;import java.awt.Toolkit;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;

public class Grafico1 extends JFrame {

private JPanel contentPane;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { Grafico1 frame = new Grafico1();

Page 161: Tutorial Java Ya 3

frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Grafico1() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setLayout(new BorderLayout(0, 0)); setContentPane(contentPane); setBounds(0,0,800,600); }

public void paint (Graphics g) { super.paint(g); Toolkit t = Toolkit.getDefaultToolkit (); Image imagen = t.getImage ("imagen1.jpg"); g.drawImage (imagen, 0, 0, this); } }

Creamos un objeto de la clase Toolkit llamando al método estático de la misma clase: Toolkit t = Toolkit.getDefaultToolkit ();

Creamos un objeto de la clase Image llamando al método getImage de la clase Toolkit pasando como parámetro el archivo con la imagen: Image imagen = t.getImage ("imagen1.jpg");

Por último llamamos al método drawImage con la referencia al objeto de tipo Image, la columna, la fila y la referencia al JFrame donde debe dibujarse: g.drawImage (imagen, 0, 0, this);

Page 162: Tutorial Java Ya 3

Método repaint()

Este es el método que con más frecuencia es llamado por el programador. El método repaint() llama ?lo antes posible? al método paint() del componente.

El método repaint() puede ser:repaint()repaint(int x, int y, int w, int h)

Las segunda forma permiten definir una zona rectangular de la ventana a la que aplicar el método.

Problema 5

Crear una aplicación que muestre un círculo en medio de la pantalla y mediante dos botones permitir que se desplace a izquierda o derecha.

import java.awt.Color;import java.awt.EventQueue;import java.awt.Graphics;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JButton;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;

public class Grafico1 extends JFrame {

private JPanel contentPane;

/** * Launch the application. */ private int columna; public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { Grafico1 frame = new Grafico1(); frame.setVisible(true);

Page 163: Tutorial Java Ya 3

} catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Grafico1() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JButton bi = new JButton("Izquierda"); bi.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { columna=columna-10; repaint(); } }); bi.setBounds(105, 482, 89, 23); contentPane.add(bi); JButton bd = new JButton("Derecha"); bd.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { columna=columna+10; repaint(); } }); bd.setBounds(556, 482, 89, 23); contentPane.add(bd); setBounds(0,0,800,600); columna=400; }

Page 164: Tutorial Java Ya 3

public void paint (Graphics g) { super.paint(g); g.setColor (Color.red); g.fillOval (columna, 300, 100, 100); } }

Definimos un atributo columna: private int columna;

Cuando se presiona el botón (bi) restamos 10 al atributo columna y pedimos que se ejecute el método paint (esto último llamando al método repaint()), el método repaint borra todo lo dibujado dentro del JFrame y llama al paint: bi.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent arg0) {columna=columna-10;repaint();

} });

El método paint dibuja un círculo utilizando como posición el valor del atributo columna: public void paint (Graphics g) { super.paint(g); g.setColor (Color.red); g.fillOval (columna, 300, 100, 100); }

Problema 6

Se debe desarrollar una pantalla para configurar ciertas características de un procesador de texto.Debe aparecer y poder seleccionarse los márgenes superior e inferior de la página.Los márgenes pueden ir en el rango de 0 a 10. Desplazar las líneas a medida que modificamos los márgenes.Por otro lado tenemos la orientación de página. La misma se administra a través de un JComboBox que tiene dos valores posibles (Horizontal y Vertical). Cuando está seleccionado en el JComboBox el String Horizontal dibujar un rectángulo con base mayor a la altura, y cuando está seleccionado el String Vertical dibujar un rectángulo con una base menor.Cuando se presiona el botón inicializar la configuración de márgenes se inicializan con 0 y se selecciona orientación horizontal.

Page 165: Tutorial Java Ya 3

Para implementar esta aplicación con el WindowBuilder creamos la interfaz visual, disponemos 4 objetos de la clase JLabel, dos JSpinner, un JButton y un objeto de la clase JComboBox. El dibulo de la hoja con las líneas de márgenes superior e inferior como el gráfico de orientación de la hoja se hacen en el método paint.El código fuente que resuelve esta aplicación es:

import java.awt.Color;import java.awt.EventQueue;import java.awt.Graphics;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JSpinner;import javax.swing.JLabel;import javax.swing.JComboBox;import javax.swing.DefaultComboBoxModel;import javax.swing.JButton;import javax.swing.SpinnerNumberModel;import javax.swing.event.ChangeListener;

Page 166: Tutorial Java Ya 3

import javax.swing.event.ChangeEvent;import java.awt.event.ItemListener;import java.awt.event.ItemEvent;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;

public class ProcesadorTexto extends JFrame {

private JPanel contentPane; private JSpinner sp1; private JSpinner sp2; private JComboBox comboBox;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { ProcesadorTexto frame = new ProcesadorTexto(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public ProcesadorTexto() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 573, 481); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane);

Page 167: Tutorial Java Ya 3

contentPane.setLayout(null); sp1 = new JSpinner(); sp1.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { repaint(); } }); sp1.setModel(new SpinnerNumberModel(0, 0, 10, 1)); sp1.setBounds(162, 51, 55, 28); contentPane.add(sp1); sp2 = new JSpinner(); sp2.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { repaint(); } }); sp2.setModel(new SpinnerNumberModel(0, 0, 10, 1)); sp2.setBounds(162, 150, 55, 28); contentPane.add(sp2); JLabel lblMargenInferior = new JLabel("Margen inferior"); lblMargenInferior.setBounds(162, 26, 109, 14); contentPane.add(lblMargenInferior); JLabel lblMargenSuperior = new JLabel("Margen superior"); lblMargenSuperior.setBounds(162, 127, 109, 14); contentPane.add(lblMargenSuperior); JLabel lblHoja = new JLabel("Hoja"); lblHoja.setBounds(46, 26, 46, 14); contentPane.add(lblHoja); comboBox = new JComboBox(); comboBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent arg0) { repaint(); } });

Page 168: Tutorial Java Ya 3

comboBox.setModel(new DefaultComboBoxModel(new String[] {"Horizontal", "Vertical"})); comboBox.setBounds(321, 55, 196, 20); contentPane.add(comboBox); JLabel lblHorientacinDePgina = new JLabel("Horientaciu00F3n de pu00E1gina."); lblHorientacinDePgina.setBounds(321, 26, 203, 14); contentPane.add(lblHorientacinDePgina); JButton btnInicializar = new JButton("Inicializar"); btnInicializar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { sp1.setValue(0); sp2.setValue(0); comboBox.setSelectedIndex(0); repaint(); } }); btnInicializar.setBounds(45, 247, 165, 23); contentPane.add(btnInicializar); } public void paint(Graphics g) { super.paint(g); g.setColor(Color.blue); g.drawRect(30,80,100,140); int ms=Integer.parseInt(sp1.getValue().toString()); int mi=Integer.parseInt(sp2.getValue().toString()); g.setColor(Color.red); g.drawLine(30,80+ms,130,80+ms); g.drawLine(30,220-mi,130,220-mi); String direccion=(String)comboBox.getSelectedItem(); if (direccion.equals("Horizontal")) g.drawRect(320,120,200,100 );

Page 169: Tutorial Java Ya 3

else g.drawRect(320,120,100,200 ); }}

Explicación del código.

Para el evento stateChanged de los controles JSpinner se debe llamar al método repaint() para que se grafique nuevamente las líneas de márgenes:

sp1.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { repaint(); } });

sp2.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { repaint(); } });

En el método paint dibujamos primero un rectángulo de color azul que representa la hoja: g.setColor(Color.blue); g.drawRect(30,80,100,140);

Extraemos los valores seleccionados de cada control JSpinner y los convertimos a tipo entero: int ms=Integer.parseInt(sp1.getValue().toString()); int mi=Integer.parseInt(sp2.getValue().toString());

Activamos el color rojo y dibujamos las dos líneas, la superior coincide con el comienzo del rectángulo (sumamos tantos pixeles en la fila como lo indica el primer JSpinner):

g.setColor(Color.red); g.drawLine(30,80+ms,130,80+ms);

La segunda línea le restamos el valor del JSpinner: g.drawLine(30,220-mi,130,220-mi);

Para saber la orientación de la hoja debemos extraer el valor seleccionado del JComboBox y mediante un if verificar si el String seleccionado es "Horizontal":

String direccion=(String)comboBox.getSelectedItem(); if (direccion.equals("Horizontal")) g.drawRect(320,120,200,100 ); else

Page 170: Tutorial Java Ya 3

g.drawRect(320,120,100,200 );

Por último cuando se presiona el botón inicializar procedemos a fijar nuevos valores a los JSpinner y al JComboBox (luego redibujamos):

btnInicializar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { sp1.setValue(0); sp2.setValue(0); comboBox.setSelectedIndex(0); repaint(); } });

Problemas propuestos1. Confeccionar un programa que permita configurar las características del mouse.

Por un lado debemos seleccionar la velocidad de desplazamiento de la flecha del mouse.

Disponer un JSpinner para poder seleccionarse los valores 0,25,50,75 y 100.

Por otro lado debemos poder seleccionar cual de los dos botones del mouse será el principal, tenemos para esta función un JComboBox con dos opciones: izquierdo o derecho.

Cuando se selecciona el botón (cambio en el JComboBox) actualizar el gráfico mostrando el botón del mouse seleccionado (graficar en el método paint el mouse en pantalla)

Page 171: Tutorial Java Ya 3

2. En una aduana hay una máquina que sortea las personas cuyo equipaje serán revisados.

La persona selecciona si viene del Interior del país o del Exterior (a través de un JComboBox), y por otro lado selecciona la cantidad de bultos (JSpinner).

Luego presiona el botón sortear y aparece al lado de este botón un círculo rojo o verde. (En caso de ser rojo se revisa su equipaje, en caso de ser verde, no se revisa)

Para el sorteo generar un valor aleatorio entre 1 y 3. Si se genera un 1 se revisa, si se genera un 2 o 3 no se revisa.

Validar que también este seleccionado un valor distinto a cero en bultos (los valores pueden ir de 0 a 10).

Si la cantidad de bultos supera a 5 se revisa siempre sus bultos (es decir que aparece un círculo rojo).

Luego de sortear fijar en cero cantidad de bultos.

Mostrar en el título del JFrame la cantidad de bultos revisados y no revisados hasta el momento.

Page 172: Tutorial Java Ya 3

58. Gráficos estadísticos

El objetivo de este concepto es la implementación de algoritmos para mostrar gráficos estadísticos.

Problema 1

Crear una aplicación que solicite el ingreso de tres valores por teclado que representan las cantidades de votos obtenidas por tres partidos políticos. Luego mostrar un gráfico de tartas:

Page 173: Tutorial Java Ya 3

El algorítmo es:

import java.awt.Color;import java.awt.EventQueue;import java.awt.Graphics;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JLabel;import javax.swing.JTextField;import javax.swing.JButton;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;

public class GraficoTarta extends JFrame {

private JPanel contentPane; private JTextField tf1; private JTextField tf2;

Page 174: Tutorial Java Ya 3

private JTextField tf3; private boolean bandera=false;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { GraficoTarta frame = new GraficoTarta(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public GraficoTarta() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 800, 600); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JLabel lblPartido = new JLabel("Partido 1:"); lblPartido.setBounds(46, 39, 61, 14); contentPane.add(lblPartido); JLabel lblPartido_1 = new JLabel("Partido 2:"); lblPartido_1.setBounds(46, 69, 61, 14); contentPane.add(lblPartido_1); JLabel lblPartido_2 = new JLabel("Partido 3:"); lblPartido_2.setBounds(46, 103, 61, 14);

Page 175: Tutorial Java Ya 3

contentPane.add(lblPartido_2); tf1 = new JTextField(); tf1.setBounds(117, 36, 86, 20); contentPane.add(tf1); tf1.setColumns(10); tf2 = new JTextField(); tf2.setBounds(117, 66, 86, 20); contentPane.add(tf2); tf2.setColumns(10); tf3 = new JTextField(); tf3.setBounds(117, 97, 86, 20); contentPane.add(tf3); tf3.setColumns(10); JButton btnGraficar = new JButton("Graficar"); btnGraficar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { bandera=true; repaint(); } }); btnGraficar.setBounds(45, 138, 107, 37); contentPane.add(btnGraficar); } public void paint(Graphics g) { super.paint(g); if (bandera==true) { String s1=tf1.getText(); String s2=tf2.getText(); String s3=tf3.getText(); int v1=Integer.parseInt(s1); int v2=Integer.parseInt(s2); int v3=Integer.parseInt(s3);

Page 176: Tutorial Java Ya 3

int suma=v1+v2+v3; int grados1=v1*360/suma; int grados2=v2*360/suma; int grados3=v3*360/suma;

g.setColor(new Color(255,0,0)); g.fillArc(50,250,200,200,0,grados1); g.fillRect(370,250,20,20); g.drawString("Partido 1", 400, 270);

g.setColor(new Color(0,128,0)); g.fillArc(50,250,200,200,grados1,grados2); g.fillRect(370,280,20,20); g.drawString("Partido 2", 400, 300);

g.setColor(new Color(0,0,255)); g.fillArc(50,250,200,200,grados1+grados2,grados3); g.fillRect(370,310,20,20); g.drawString("Partido 1", 400, 330); } } }

Disponemos un if en el método paint para controlar que se haya presionado el botón graficar: public void paint(Graphics g) { super.paint(g); if (bandera==true) {

El atributo bandera se inicializa cuando se define con el valor false, esto hace que cuando se ejecute por primera vez el método paint no ingrese al if: private boolean bandera=false;

Se definen tres objetos de la clase JTextField para ingresar los tres valores por teclado: private JTextField tf1; private JTextField tf2; private JTextField tf3;

Cuando se presiona el botón se cambia el estado del atributo bandera por el valor true y se llama al método repaint (recordemos que este método borra el JFrame y llama al método paint para que ahora dibuje el gráfico de tarta):

Page 177: Tutorial Java Ya 3

btnGraficar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { bandera=true; repaint(); } });

Lo primero que hacemos para graficar la tarta es rescatar los tres valores ingresados en los controles JTextField: if (bandera==true) { String s1=tf1.getText(); String s2=tf2.getText(); String s3=tf3.getText();

Los convertimos a tipo de dato entero: int v1=Integer.parseInt(s1); int v2=Integer.parseInt(s2); int v3=Integer.parseInt(s3);

Sumamos los tres valores: int suma=v1+v2+v3;

Seguidamente calculamos los grados que le corresponde a cada trozo de tarta (teniendo en cuenta que tenemos 360 grados para repartir):

Cada trozo de tarta lo obtenemos mediante la ecuación:tamaño trozo= cantidad de votos del partido/ total de votos * 360

si observamos la ecuación podemos imaginar que la división:cantidad de votos del partido / total de votos

generará un valor menor a uno (salvo que el partido haya obtenido todos los votos de la elección en cuyo caso la división genera el valor uno)

Esta división nos genera el porcentaje de votos que le corresponde al partido y luego dicho porcentaje lo multiplicamos por la cantidad de grados a repartir (que son 360 grados)

Luego como la división generará un valor menor a uno y al tratarse de dos variables enteras el resultado será cero. Para evitar este problema procedemos primero a multiplicar por 360 y luego dividir por la variable suma: int grados1=v1*360/suma; int grados2=v2*360/suma; int grados3=v3*360/suma;

Si quisiéramos primero dividir y luego multiplicar por 360 debemos proceder a anteceder a cada operación el tipo de resultado a obtener: int grados1=(int)((float)v1/suma*360); int grados2=(int)((float)v2/suma*360); int grados3=(int)((float)v3/suma*360);

Como podemos ver es más complicado si queremos primero efectuar la división y luego el producto.

Page 178: Tutorial Java Ya 3

Procedemos ahora a graficar los trozos de tarta y leyenda con el valor ingresado (activamos el color rojo y mediante el método fillArc creamos un trozo de tarta que se inicia en el grado 0 y avanza tantos trados como indica la variable grados1. Luego mediante el método drawString mostramos la leyenda del partido respectivo con un cuadradito también de color rojo ): g.setColor(new Color(255,0,0)); g.fillArc(50,250,200,200,0,grados1); g.fillRect(370,250,20,20); g.drawString("Partido 1", 400, 270);

El segundo trozo comienza en grados1 y avanza tantos grados como lo indica la variable grados2. Activamos el color verde para diferenciar del trozo anterior: g.setColor(new Color(0,128,0)); g.fillArc(50,250,200,200,grados1,grados2); g.fillRect(370,280,20,20); g.drawString("Partido 2", 400, 300);

El último trozo lo graficamos a partir de la suma de grados1+grados2 y avanzamos tantos grados como lo indica la variable grados3: g.setColor(new Color(0,0,255)); g.fillArc(50,250,200,200,grados1+grados2,grados3); g.fillRect(370,310,20,20); g.drawString("Partido 1", 400, 330);

Problema 2

Crear una aplicación que solicite el ingreso de tres valores por teclado que representan las cantidades de votos obtenidas por tres partidos políticos. Luego mostrar un gráfico de barras horizontales:

Page 179: Tutorial Java Ya 3

El algorítmo es:

import java.awt.Color;import java.awt.EventQueue;import java.awt.Graphics;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JLabel;import javax.swing.JTextField;import javax.swing.JButton;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;

public class GraficoBarraHorizontal extends JFrame {

private JPanel contentPane; private JTextField tf3; private JTextField tf1; private JTextField tf2; private boolean bandera=false;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { GraficoBarraHorizontal frame = new GraficoBarraHorizontal(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame.

Page 180: Tutorial Java Ya 3

*/ public GraficoBarraHorizontal() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 800, 600); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JLabel lblPartido = new JLabel("Partido 1:"); lblPartido.setBounds(46, 39, 61, 14); contentPane.add(lblPartido); JLabel lblPartido_1 = new JLabel("Partido 2:"); lblPartido_1.setBounds(46, 69, 61, 14); contentPane.add(lblPartido_1); JLabel lblPartido_2 = new JLabel("Partido 3:"); lblPartido_2.setBounds(46, 103, 61, 14); contentPane.add(lblPartido_2); tf1 = new JTextField(); tf1.setBounds(117, 36, 86, 20); contentPane.add(tf1); tf1.setColumns(10); tf2 = new JTextField(); tf2.setBounds(117, 66, 86, 20); contentPane.add(tf2); tf2.setColumns(10); tf3 = new JTextField(); tf3.setBounds(117, 97, 86, 20); contentPane.add(tf3); tf3.setColumns(10); JButton btnGraficar = new JButton("Graficar"); btnGraficar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { bandera=true;

Page 181: Tutorial Java Ya 3

repaint(); } }); btnGraficar.setBounds(45, 138, 107, 37); contentPane.add(btnGraficar); } public void paint(Graphics g) { super.paint(g); if (bandera==true) { String s1=tf1.getText(); String s2=tf2.getText(); String s3=tf3.getText(); int v1=Integer.parseInt(s1); int v2=Integer.parseInt(s2); int v3=Integer.parseInt(s3); int mayor=retornarMayor(v1,v2,v3); int largo1=v1*400/mayor; int largo2=v2*400/mayor; int largo3=v3*400/mayor;

g.setColor(new Color(255,0,0)); g.fillRect(100,250,largo1,40); g.drawString("Partido 1", 10, 270);

g.setColor(new Color(0,128,0)); g.fillRect(100,300,largo2,40); g.drawString("Partido 2", 10, 320);

g.setColor(new Color(0,0,255)); g.fillRect(100,350,largo3,40); g.drawString("Partido 3", 10, 370); } } private int retornarMayor(int v1,int v2,int v3) {

Page 182: Tutorial Java Ya 3

if (v1>v2 && v1>v3) return v1; else if (v2>v3) return v2; else return v3; } }

La metodología es similar al problema anterior. Ahora no tenemos grados para repartir, por lo que implementaremos el siguiente algoritmo:

Consideraremos que el partido que obtuvo más votos le corresponde una barra de 400 píxeles de largo y los otros dos partidos se les entregará en forma proporcional.

Lo primero que hacemos es obtener el mayor de los tres valores ingresados por teclado, para esto implementamos un método privado que retorne el mayor de tres valores enteros: private int retornarMayor(int v1,int v2,int v3) { if (v1>v2 && v1>v3) return v1; else if (v2>v3) return v2; else return v3; }

El el método paint llamamos al método retornarMayor: int mayor=retornarMayor(v1,v2,v3);

La ecuación para obtener el largo de la barra será:largo=votos del partido/votos del partido con mas votos * 400 píxeles.

Como podemos ver esta división generará un valor menor a uno salvo para el partido que tiene más votos (en este caso la división genera el valor 1) luego multiplicamos por 400.

Comenzamos a calcular el largo de cada rectángulo: int largo1=v1*400/mayor;

Como podemos ver primero multiplicamos por 400 y lo dividimos por el mayor de los tres valores ingresados.Nuevamente primero multiplicamos y luego dividimos con el objetivo que el resultado de la división no nos redondee a cero.

El primer trozo lo graficamos a partir de la columna 100, fila 250 y con un ancho indicado en la variable largo1 (el alto de la barra es de 40 píxeles): g.setColor(new Color(255,0,0));

Page 183: Tutorial Java Ya 3

g.fillRect(100,250,largo1,40); g.drawString("Partido 1", 10, 270);

En forma similar graficamos los otros dos trozos de barra:

g.setColor(new Color(0,128,0)); g.fillRect(100,300,largo2,40); g.drawString("Partido 2", 10, 320);

g.setColor(new Color(0,0,255)); g.fillRect(100,350,largo3,40); g.drawString("Partido 3", 10, 370);

Problema propuesto1. Implementar un gráfico estadístico de tipo "Barra Porcentual":

Solución

import java.awt.Color;

public class BarraPorcentual extends JFrame {

private JPanel contentPane; private JTextField tf1; private JTextField tf2; private JTextField tf3; private boolean bandera=false;

/**

Page 184: Tutorial Java Ya 3

* Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { BarraPorcentual frame = new BarraPorcentual(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public BarraPorcentual() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 800, 600); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JLabel lblPartido = new JLabel("Partido 1:"); lblPartido.setBounds(46, 39, 61, 14); contentPane.add(lblPartido); JLabel lblPartido_1 = new JLabel("Partido 2:"); lblPartido_1.setBounds(46, 69, 61, 14); contentPane.add(lblPartido_1); JLabel lblPartido_2 = new JLabel("Partido 3:"); lblPartido_2.setBounds(46, 103, 61, 14); contentPane.add(lblPartido_2); tf1 = new JTextField(); tf1.setBounds(117, 36, 86, 20); contentPane.add(tf1); tf1.setColumns(10); tf2 = new JTextField(); tf2.setBounds(117, 66, 86, 20); contentPane.add(tf2); tf2.setColumns(10); tf3 = new JTextField();

Page 185: Tutorial Java Ya 3

tf3.setBounds(117, 97, 86, 20); contentPane.add(tf3); tf3.setColumns(10); JButton btnGraficar = new JButton("Graficar"); btnGraficar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { bandera=true; repaint(); } }); btnGraficar.setBounds(45, 138, 107, 37); contentPane.add(btnGraficar); } public void paint(Graphics g) { super.paint(g); if (bandera==true) { String s1=tf1.getText(); String s2=tf2.getText(); String s3=tf3.getText(); int v1=Integer.parseInt(s1); int v2=Integer.parseInt(s2); int v3=Integer.parseInt(s3); int suma=v1+v2+v3; int largo1=v1*400/suma; int largo2=v2*400/suma; int largo3=v3*400/suma; int porc1=v1*100/suma; int porc2=v2*100/suma; int porc3=v3*100/suma; g.setColor(new Color(255,0,0)); g.fillRect(50,250,largo1,50); g.setColor(new Color(255,255,255)); g.drawString(porc1+"%",55,270); g.setColor(new Color(0,128,0)); g.fillRect(50+largo1,250,largo2,50); g.setColor(new Color(255,255,255)); g.drawString(porc2+"%",55+largo1,270); g.setColor(new Color(0,0,255)); g.fillRect(50+largo1+largo2,250,largo3,50); g.setColor(new Color(255,255,255)); g.drawString(porc3+"%",55+largo1+largo2,270);

Page 186: Tutorial Java Ya 3

} } }

59. JDBC con MySQLDBC son las siglas en ingles de Java Database Connectivity. Es un conjunto de clases que nos permite acceder a diversos gestores de bases de datos en forma transparente.Veremos como conectarnos con el motor de base de datos MySQL.

Instalación de MySQL integrado en el WampServer

Utilizaremos esta herramienta en lugar de descargar solo el MySQL con la finalizar de facilitar la instalación y configuración del motor de base de datos (la instalación de esta herramienta es sumamente sencilla), además utilizaremos otra software que provee el WampServer que es el PhpMyAdmin que nos facilitará la creación de la base de datos.Procedemos a descargar el WampServer de la siguiente página: aquí.

http://www.wampserver.com/en/#download-wrapper

Luego de descargarlo procedemos a ejecutar el instalador:

Page 187: Tutorial Java Ya 3

Aceptamos los términos y condiciones:

Elegimos el directorio donde se instalará":

Page 188: Tutorial Java Ya 3

Indicamos si queremos que se cree un ícono en el escritorio:

Procedemos a presionar el botón "Install":

Page 189: Tutorial Java Ya 3

Luego de instalarse nos solicita que navegador abrirá por defecto cuando ejecutemos el PhpMyAdmin (para la creación de la base de datos de MySQL):

Page 190: Tutorial Java Ya 3

En el siguiente diálogo dejamos los datos por defecto:

Finalmente aparece el diálogo final donde se nos informa que se iniciará el WampServer (es decir que se cargará en memoria entre otras cosas el MySQL) :

Page 191: Tutorial Java Ya 3

Ahora podemos ver el iconos del WampServer en la bandeja del sistema de Windows (si se encuentra en color verde significa que el MySQL está ejecutándose correctamente):

Ejecución del PhpMyAdmin para la creación de la base de datos.

Haciendo clic sobre el ícono de la bandeja del sistema aparece un menú que nos permite lanzar el PhpMyAdmin para crear la base de datos de MySQL:

El PhpMyAdmin es un programa web que nos permite administrar las bases de datos del MySQL:

Page 192: Tutorial Java Ya 3

Seleccionamos la pestaña "Base de datos" y donde dice "Crear nueva base de datos" especificamos que nuestra base de datos se llamará "bd1":

Page 193: Tutorial Java Ya 3

Presionamos el botón "crear" y con esto ya tenemos nuestra base de datos creada:

Page 194: Tutorial Java Ya 3

Luego de seleccionar la base de datos "bd1" que figura a la izquierda procedemos a crear la primer tabla que contendrá (crearemos una tabla llamada "articulos" y que tendrá tres campos):

Page 195: Tutorial Java Ya 3

En la tabla "articulos" definimos el campo "codigo" de tipo int (este campo será el "primary key" y auto_increment lo tildamos para que el código se genere automáticamente), el segundo campo es la descripción que es de tipo varchar con un máximo de 50 caracteres y por último el campo precio que es de tipo float.Luego de especificar los tres campos en la parte inferior de la misma ventana aparece un un botón llamada "Guardar" para confirmar la estructura de la tabla:

Page 196: Tutorial Java Ya 3

En el lado izquierdo del navegador podemos ver ahora que la base de datos "bd1" tiene una tabla llamada "articulos"

Page 197: Tutorial Java Ya 3

Hasta acá lo que nos ayuda el PhpMyAdmin (es decir creación de la base de datos y la tabla), de ahora en más todas las otras actividades las desarrollaremos desde nuestro programa en java (poblar o insertar datos, listar registros, consultar, modificar y borrar datos)

Descarga del Driver para permitir conectar nuestro programa Java con el MySQL

Como última actividad de configuración previo a implementar los programas en Java para acceder a MySQL es la descarga del Driver que nos permita conectarnos con la base de datos.El Driver lo podemos descargar de la página:aquí

http://dev.mysql.com/downloads/connector/j/

Podemos descomprimir el archivo mysql-connector-java-5.1.18.zip que acabamos de descargar. Luego veremos que en nuestro programa en java haremos referencias al archivo mysql-connector-java-5.1.18-bin.jar (que es el Driver propiamente dicho)

60. Alta y Consulta de una tabla de MySQL

Problema 1

Ya creamos en el concepto anterior una base de datos llamada bd1 y en la misma creamos una tabla llamada articulos.Procederemos a implementar en Java un programa que nos permita comunicarnos con la base de datos "bd1" e insertar filas en la tabla "articulos" y posteriormente consultar su contenido.1 - Creamos desde Eclipse un proyecto llamado "basededatos01" y seguidamente con el WindowBuilder creamos una clase llamada "Formulario".2 - Primero debemos añadir el driver que descargamos (mysql-connector-java-5.1.18-bin.jar) presionamos el botón derecho del mouse sobre nuestro proyecto y seleccionamos la opción "Properties", aparece el siguiente diálogo:

Page 198: Tutorial Java Ya 3

Seleccionamos la opción "Java Build Path", de la parte central seleccionamos la pestaña "Libraries" y procedemos a presionar el botón "Add External JARs...", donde procedemos a buscar el archivo mysql-connector-java-5.1.18-bin.jarEl código fuente de la clase formulario es:

import java.awt.EventQueue;

import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import javax.swing.JLabel;import javax.swing.JTextField;import javax.swing.JButton;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;

Page 199: Tutorial Java Ya 3

import java.sql.SQLException;import java.sql.Statement;

public class Formulario extends JFrame {

private JPanel contentPane; private JTextField tf1; private JTextField tf2; private JLabel labelResultado; private JButton btnConsultaPorCdigo; private JLabel lblIngreseCdigoDe; private JTextField tf3;

/** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { Formulario frame = new Formulario(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); }

/** * Create the frame. */ public Formulario() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 606, 405); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JLabel lblDescripcinDelArtculo = new JLabel("Descripción del artículo:"); lblDescripcinDelArtculo.setBounds(23, 38, 193, 14); contentPane.add(lblDescripcinDelArtculo); tf1 = new JTextField(); tf1.setBounds(247, 35, 193, 20); contentPane.add(tf1);

Page 200: Tutorial Java Ya 3

tf1.setColumns(10); JLabel lblPrecio = new JLabel("Precio:"); lblPrecio.setBounds(23, 74, 95, 14); contentPane.add(lblPrecio); tf2 = new JTextField(); tf2.setBounds(247, 71, 107, 20); contentPane.add(tf2); tf2.setColumns(10); JButton btnAlta = new JButton("Alta"); btnAlta.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { labelResultado.setText(""); try { Connection conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,""); Statement comando=conexion.createStatement(); comando.executeUpdate("insert into articulos(descripcion,precio) values ('"+tf1.getText()+"',"+tf2.getText()+")"); conexion.close(); labelResultado.setText("se registraron los datos"); tf1.setText(""); tf2.setText(""); } catch(SQLException ex){ setTitle(ex.toString()); } } }); btnAlta.setBounds(247, 118, 89, 23); contentPane.add(btnAlta); labelResultado = new JLabel("resultado"); labelResultado.setBounds(361, 122, 229, 14); contentPane.add(labelResultado); btnConsultaPorCdigo = new JButton("Consulta por código"); btnConsultaPorCdigo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { labelResultado.setText(""); tf1.setText(""); tf2.setText(""); try { Connection conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,"");

Page 201: Tutorial Java Ya 3

Statement comando=conexion.createStatement(); ResultSet registro = comando.executeQuery("select descripcion,precio from articulos where codigo="+tf3.getText()); if (registro.next()==true) { tf1.setText(registro.getString("descripcion")); tf2.setText(registro.getString("precio")); } else { labelResultado.setText("No existe un artículo con dicho código"); } conexion.close(); } catch(SQLException ex){ setTitle(ex.toString()); } } }); btnConsultaPorCdigo.setBounds(23, 212, 177, 23); contentPane.add(btnConsultaPorCdigo); lblIngreseCdigoDe = new JLabel("Ingrese código de articulo a consultar:"); lblIngreseCdigoDe.setBounds(10, 179, 243, 14); contentPane.add(lblIngreseCdigoDe); tf3 = new JTextField(); tf3.setBounds(247, 176, 86, 20); contentPane.add(tf3); tf3.setColumns(10); cargarDriver(); } private void cargarDriver() { try { Class.forName("com.mysql.jdbc.Driver"); }catch(Exception ex) { setTitle(ex.toString()); } }}

La interfaz visual de la aplicación a implementar es la siguiente (se solicita el ingrese de la descripción del artículo y su precio, cuando se presiona el botón "Alta" se procede a insertar una fila en la tabla articulos de la base de datos bd1):

Page 202: Tutorial Java Ya 3

Expliquemos ahora el código fuente de la aplicación:Primero debemos cargar en memoria el Driver, esto lo hacemos mediante el método cargarDriver que es llamado luego desde el constructor de la clase:

private void cargarDriver() { try { Class.forName("com.mysql.jdbc.Driver"); }catch(Exception ex) { setTitle(ex.toString()); } }

Tenemos una clase llamada "Class" que tiene un método estático llamado forName, al mismo hay que pasar el nombre de la clase a importar:

Class.forName("com.mysql.jdbc.Driver");

com.mysql.jdbc es el nombre del paquete donde se encuentra la clase Driver. Esta el la forma que importamos los driver en Java.El método forName de la clase Class genera excepciones de tipo Excepcion que deben ser capturadas obligatoriamente (luego por eso encerramos el código en un bloque try/catch.Si no importamos el driver desde el diálogo Properties del proyecto o indicamos en forma incorrecta el nombre del paquete o clase luego aparece en el título del JFrame un mensaje del error sucedido.Luego desde el constructor llamamos por única vez al método cargarDriver:

...........tf3 = new JTextField();

Page 203: Tutorial Java Ya 3

tf3.setBounds(247, 176, 86, 20);contentPane.add(tf3);tf3.setColumns(10);cargarDriver();

}

Veamos ahora cual es el código a implementar cuando se presiona el botón "Alta":

JButton btnAlta = new JButton("Alta"); btnAlta.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { labelResultado.setText(""); try { Connection conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,""); Statement comando=conexion.createStatement(); comando.executeUpdate("insert into articulos(descripcion,precio) values ('"+tf1.getText()+"',"+tf2.getText()+")"); conexion.close(); labelResultado.setText("se registraron los datos"); tf1.setText(""); tf2.setText(""); } catch(SQLException ex){ setTitle(ex.toString()); } } });

En el actionPerformed procedemos primero a limpiar la label que puede tener un mensaje de ejecuciones anteriores:

labelResultado.setText("");

Todas las clases orientadas al acceso a base de datos generan excepciones de tipo SQLException y deben ser capturadas obligatoriamente. Lo primero que hacemos es crear un objeto de la clase Connection, para esto la clase DriverManager tiene un método llamado getConnection que retorna un objeto de la clase Connection:

Connection conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,"");

El método getConnection debemos pasarle tres String, el primero indica el nombre de la base de datos que queremos acceder (en este caso "bd1"), el segundo parámetro es el nombre de usuario (recordemos que cuando instalamos el MySQL se crea un usuario por defecto llamado "root") y el último parámetro el la clave del usuario "root", por defecto esta clave es un String vacío.Como podemos ver también previo a la base de datos tenemos en la cadena de conexión el nombre de nuestro servidor (localhost)

Page 204: Tutorial Java Ya 3

Si nos equivocamos por ejemplo con el nombre de base de datos a comunicarnos (por ejemplo cambiar "bd1" por "bdx") veremos en el título del JFrame el mensaje de error que nos devuelve el MySQL:

Luego creamos un objeto de la clase Statement a partir del objeto de la clase Connection que acabamos de crear:

Statement comando=conexion.createStatement();

La clase Statement tiene un método llamado executeUpdate que le pasamos el comando SQL insert para agregar una fila a la tabla articulos:

comando.executeUpdate("insert into articulos(descripcion,precio) values ('"+tf1.getText()+"',"+tf2.getText()+")");

Como podemos ver generamos el String con el comando insert rescatando los datos de los dos controles de tipo JTextField. Es importante notar que en Java los String están encerrados entre comillas dobles y los contatenamos con el operador +. Las comillas simples son necesarias para los campos de tipo varchar de MySql (como podemos notar el lugar donde se dispondrá el texto de la descripción del artículo deben ir obligatoriamente las comillas simples):

...'"+tf1.getText()+"'...

Si nos olvidamos las comillas simples al generar el String con el comando Insert el MySQL nos devolverá un error que será capturado por el try/catch, por ejemplo si lo ejecutamos con la siguiente sintaxis (sin las comillas simples envolviendo el valor de la descripción):

Page 205: Tutorial Java Ya 3

comando.executeUpdate("insert into articulos(descripcion,precio) values ("+tf1.getText()+","+tf2.getText()+")");

Luego de solicitar la ejecución del comando Insert al MySQL procedemos a llamar al método close de la clase Connection:

conexion.close();

Con lo visto ya podemos agregar filas a la tabla articulos. Veamos ahora como consultar datos. El código a implementar cuando se presiona el botón "Consulta por código" es el siguiente:

btnConsultaPorCdigo = new JButton("Consulta por código");btnConsultaPorCdigo.addActionListener(new ActionListener()

{public void actionPerformed(ActionEvent arg0) {

labelResultado.setText("");tf1.setText("");tf2.setText("");try {

Connection conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,"");

Statement comando=conexion.createStatement();

Page 206: Tutorial Java Ya 3

ResultSet registro = comando.executeQuery("select descripcion,precio from articulos where codigo="+tf3.getText());

if (registro.next()==true) {

tf1.setText(registro.getString("descripcion"));

tf2.setText(registro.getString("precio"));} else {

labelResultado.setText("No existe un artículo con dicho código");

}conexion.close();

} catch(SQLException ex){setTitle(ex.toString());

}}

});

De forma similar al Insert procedemos a crear un objeto de la clase Connection y otro objeto de la clase Statement:

Connection conexion=DriverManager.getConnection("jdbc:mysql://localhost/bd1","root" ,"");

Statement comando=conexion.createStatement();

Seguidamente definimos una variable de la clase ResultSet llamada registro y llamamos al método executeQuery de la clase Statement del objeto que acabamos de crear previamente:

ResultSet registro = comando.executeQuery("select descripcion,precio from articulos where codigo="+tf3.getText());

La clase ResultSet lo podemos imaginar como una tabla con todos los datos recuperados del comando SQL select que acaba de ejecutar el MySQL. En este ejemplo puede retornar una fila o ninguna ya que estamos utilizando la cláusula where y preguntando por el campo clave codigo.Para acceder al registro devuelto debemos llamar al método next(), si retorna true es que si se recuperó una fila de la tabla articulos (es decir si existe el codigo de articulo ingresado), en caso que retorne false el método next() significa que no hay un artículo con el código que ingresamos en el control JTextField:

if (registro.next()==true) {

tf1.setText(registro.getString("descripcion"));

tf2.setText(registro.getString("precio"));} else {

labelResultado.setText("No existe un artículo con dicho código");

}

Page 207: Tutorial Java Ya 3

Este proyecto lo puede descargar en un zip desde este enlace: basededatos01.zip