Java Basico - 03
Java Basico - 03
Programación en Java
Parte 3: Uso del Equipo de Herramientas Gráficas para
Ventanas
Objetivo General
Aprender el uso de los diferentes objetos gráficos que se agregan a las
ventanas y Applets para leer o mostrar de datos.
Introducción
Cuando se hacen Applets o aplicaciones en Java con ventanas es muy común utilizar el equipo de
herramientas gráficas AWT (Abstract Windowing Toolkit) ya que son las que proporcionan el soporte gráfico
necesario para las interfazs que más gustan a los usuarios actuales. AWT es un paquete que contiene
numerosas clases y métodos que permiten crear y gestionar ventanas. Una descripción completa del AWT
sería bastante extensa, por lo que se tratarán los temas más relevantes.
La clase Graphics incluye métodos que permiten hacer dibujos de línea y texto, así como pintura de imagen.
Se le utiliza como parámetro del método paint() de la clase Applet. y no es posible instanciarlo directamente
al igual que la clase Image, el cual se puede obtener mediante el método Applet.getImage().
Las clases Font y Color permiten modificar la apariencia del texto que se pueda desplegar, tanto en los
componentes como por otro medio.
Los componentes GUI son los que pueden aparecer en interfazs y menús. Clases como la Applet actúan
como contenedores de estos componentes y los acomodan visualmente. Se pueden agregar componentes a
un contenedor con el método add() y especificar un administrador de diseño para el contenedor con el
método setLayout().
Componente Clase
Etiqueta Label
1
Instituto Tecnológico Metropolitano
• En una rejilla de filas y columnas que no • En un conjunto de fichas con pestañas donde
necesariamente tienen la misma altura y sólo se muestra la que está en la parte
ancho y que ajusta el tamaño de las celdas superior
según sea adecuado para asegurar que los
componentes no se traslapen
(GridBagLayout).
El paquete AWT define ventanas en función de una jerarquía de clases que añade funcionalidad y carácter
específico con cada nivel. Las dos ventanas más comunes son las que derivan de Panel, que las utilizan los
Applets, y las que derivan de Frame (marco), que permiten crear una ventana estándar.
Clase Descripción
Canvas Crea una ventana sin una semántica asociada
CheckboxMenuIte Crea un elemento del menú del tipo encendido/apagado
m
Component Es una superclase abstracta de varios componentes del AWT
Container Es una subclase abstracta de Component que puede contener otros componentes
Dialog Crea una ventana de diálogo
Dimension Especifica las dimensiones de un objeto. El ancho se almacena en width y el alto en
2
Instituto Tecnológico Metropolitano
height
Event Encapsula eventos
FileDialog Crea una ventana desde la que se puede seleccionar un archivo
Frame Crea una ventana que tiene una barra de título, esquinas que permiten cambiar el
tamaño de la ventana y un menú.
Insets Encapsula los bordes de un contenedor
MediaTracker Gestor de carga
Menu Crea un menú desplegable
MenuBar Crea una barra de menú
MenuComponent Clase abstracta implementada por varias clases del menú
MenuItem Crea un elemento de un menú
Panel Es una subclase de Container
Point Encapsula un par de coordenadas cartesianas almacenadas en x y y.
Polygon Encapsula un polígono
Rectangle Encapsula un rectángulo
Scrollbar Crea una barra de desplazamiento
TextArea Crea el control para un área de texto con varias líneas
TextComponent Es una superclase de TextArea y TextField
Toolkit Clase abstracta implementada por el AWT
Window Crea una ventana sin marco, sin menú ni título
Se trata de realizar un Applet que simule una pequeña calculadora con las operaciones básicas. Los
componentes a utilizar son los siguientes:
Observamos que el Applet en primer lugar es un contenedor de la clase Panel. El diseño del contenedor
corre a cargo de la clase GridBagLayout, la cual distribuye los controles de acuerdo a parámetros
especificados a través de la clase GridBrgConstraints. En la única celda de la primer fila del administrador
de diseño (la cual comprende las 5 celdas inferiores), irá una caja de texto para leer y mostrar números. En
las celdas inferiores (fila 2) irán botones de comando que activarán cada una de las operaciones disponibles.
Son los objetos que tendrán asociados sucesos.
Para que la aplicación pueda reaccionar a sucesos que ocurren con los botones de comando debe heredar
la interfaz que permite “escuchar” eventos de acción en componentes AWT. Esta es la clase ActionListener,
3
Instituto Tecnológico Metropolitano
la cual mediante el método actionPerformed() es notificada cuando ocurre un ActionEvent con cualquiera
de los objetos registrados mediante el respectivo método addActionListener().
ActionEvent es la clase que representa un evento de “Acción” generado por un componente AWT (los
correspondientes a las clases Button y MenuItem). El método getActionCommand() devuelve el String
correspondiente a la acción definida para el componente mediante el respectivo método
setActionCommand().
El siguiente es el código para este Applet. En el método init() (El cual se superpone, es decir, viene heredado
de la clase Applet pero se modifica) se define como será su aspecto y las acciones que se pueden activar.
La caja de texto es global para poder ser utilizada en los distintos métodos, mientras los botones sólo son
definidos inicialmente, ya que posteriormente sólo son referenciadas las acciones asociadas (en el método
actionPerformed()). Se definen 5 acciones: 4 para activar las operaciones aritméticas y 1 para mostrar el
resultado. Dado que se utiliza una sala caja de texto para leer y mostrar datos, los valores temporales son
almacenados en la variable memoria.
/* Definir características de las celdas siguientes de la segunda fila y agregar los respectivos botones */
Button bntR=new Button("-");
gbc.gridx=2;
add(bntR,gbc);
4
Instituto Tecnológico Metropolitano
gbc.gridx=5;
add(bntI,gbc);
/* Definir las acciones asociadas a los botones de commando y agregarlas al escuchador de eventos de acción
*/
bntS.setActionCommand("Sum");bntS.addActionListener(this);
bntR.setActionCommand("Res");bntR.addActionListener(this);
bntM.setActionCommand("Mul");bntM.addActionListener(this);
bntD.setActionCommand("Div");bntD.addActionListener(this);
bntI.setActionCommand("Igu");bntI.addActionListener(this);
}
/* Si la acción corresponde a una operación aritmética, se conservan el valor digitado y la operación activada */
if(accion.equals("Sum"))
{
memoria=d.doubleValue();
operador=1;
txtNum.setText("");
}
if(accion.equals("Res"))
{
memoria=d.doubleValue();
operador=2;
txtNum.setText("");
}
if(accion.equals("Mul"))
{
memoria=d.doubleValue();
operador=3;
txtNum.setText("");
}
if(accion.equals("Div"))
{
memoria=d.doubleValue();
operador=4;
txtNum.setText("");
}
/* Si la acción es el calculo del resultado final, se calcula y se muestra */
if(accion.equals("Igu"))
{
double valor=memoria;
switch(operador)
{
case 1:
valor+=d.doubleValue();
break;
case 2:
valor-=d.doubleValue();
break;
case 3:
valor*=d.doubleValue();
break;
case 4:
5
Instituto Tecnológico Metropolitano
if(d.doubleValue()!=0)
valor/=d.doubleValue();
else
valor=0;
break;
}
txtNum.setText(String.valueOf(valor));
}
}
}
Se trata de listar los departamentos de la república de Colombia y cuando se elija uno, se muestra el
respectivo mapa.
Para ello el Applet incluye un objeto de la clase Choice el cual permite elegir una opción en una lista
desplegable. Para indicar que clase de opciones se listan, se añade un objeto de clase Label el cual permite
mostrar texto que no es editable (Lo cual lo diferencia de la clase TextField).
Para que la aplicación pueda reaccionar a sucesos que ocurren con la lista debe heredar la interfaz que
permite “escuchar” eventos de selección en componentes AWT. Esta es la clase ItemListener, la cual
mediante el método itemStateChanged() es notificada cuando ocurre un ItemEvent con cualquiera de los
objetos registrados mediante el respectivo método addItemListener().
ItemEvent es la clase que representa un evento de “Selección” generado por un componente AWT (los
correspondientes a las clases Choice, List y Checkbox). El método getItemSelectable() devuelve el objeto
que activa el suceso.
La lista desplegable se llena con los nombres de los departamentos de Colombia los cuales se almacenan
en el vector de String strDepto. Paralelo a este vector se tiene otro llamado strArchivoDepto el cual
contiene los nombres de los archivos con la imágenes de los mapas de cada uno de los departamentos. De
esta manera, cuando se elige un departamento de la lista, se obtiene el nombre del archivo de la imagen.
6
Instituto Tecnológico Metropolitano
Los objetos de la clase Choice tienen el método addItem() para agregar opciones a la lista. El método
getSelectedIndex() sirve para saber cual fue la opción escogida. El método removeAll() quita todas las
opciones.
El código del Applet se completa con las instrucciones que muestran la imagen del mapa del departamento.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
8
Instituto Tecnológico Metropolitano
}
}
Un ejemplo de una interfaz que hace un uso ilustrativo del paquete java.awt es la siguiente:
9
Instituto Tecnológico Metropolitano
Esta es una interfaz de un Applet que permite a un usuario calcular el valor de una llamada telefónica con
base en la duración, el destino, la tarifa y el horario.
Para obtener la apariencia inicial de la interfaz del ejemplo, se declaran los componentes y se superpone el
código de los métodos init() y paint() de un Applet en los cuales se codifica el estado inicial del Applet:
import java.Applet.Applet;
import java.awt.*;
import java.awt.event.*;
11
Instituto Tecnológico Metropolitano
12
Instituto Tecnológico Metropolitano
gbcLlamada.gridx=1;gbcLlamada.gridy=6;
add(cmdCalcular, gbcLlamada);
}
/* método para mostrar grágicos en el Applet */
public void paint(Graphics g){
Image imgLogo=getImage(getDocumentBase(),"Orbitel.gif");
g.drawImage(imgLogo,0,0,this);
}
Observe que algunos componentes se declaran fuera del método init() y otros dentro de él. Los que se
declaran fuera son elementos globales del Applet, es decir, que se pueden reconocer en cualquier método.
Los que se declaran dentro del método init() tales como algunas etiquetas y los administradores de diseño,
sólo se necesitan inicialmente.
Para agregar cada componente al Applet, se utiliza un objeto GridBagConstraint el cual define como se
ubicará dentro de la rejilla del GridBagLayout. Para ello se actualizan algunas propiedades
GridBagConstraint:
gbcLlamada.gridx=2;gbcLlamada.gridy=2;
gbcLlamada.gridwidth=2;
add(txtDuracion, gbcLlamada);
Para usar un tipo de letra observe el método constructor font() de la clase Font el cual pide especificar la
fuente, el estilo (Usando los atributos constantes ITALIC, BOLD) y el tamaño. El tipo de letra se asigna a los
componentes con el método setFont().
Para usar un color se utilizan los atributos de la clase Color identificados con el nombre del color: black,
blue, cyan, darkGray, gray, green, lightGray, magenta, orange, pink, red, white y yellow. Y se asigna al
componente con el método setForeground().
lblTitulo.setForeground(Color.blue);
Image imgLogo=getImage(getDocumentBase(),"Orbitel.gif");
g.drawImage(imgLogo,0,0,this);
13
Instituto Tecnológico Metropolitano
Para que componentes de la clase Checkbox actúen como botones de radio y no como cajas de chequeo,
deben agruparse en un objeto CheckboxGroup. Para ello en el método constructor Checkbox() se debe
especificar el respectivo objeto CheckboxGroup al que pertenecen.
Para definir las opciones de la lista desplegable, se debe utilizar el método addItem() de la respectiva clase
(Choice).
cmbHora.addItem("Mañana");
cmbHora.addItem("Tarde");
cmbHora.addItem("Noche");
cmbHora.addItem("Madrugada");
La opciones de la lista de tarifas dependen del destino elegido y por tanto varían. Para ello se definen unos
vectores constantes que permitirán llenar la lista.
Cuando se trata de definir un vector de clases se utiliza el identificador del método constructor seguido de
corchetes entre los cuales puede ir el tamaño del vector. Si se desea especificar los valores iniciales del
vector se pueden escribir a continuación entre llaves y separados por coma.
String[] strDestinoInternal=new String[] {"EE UU y Canadá", …}
Dado que la interfaz es un Applet y además debe responder a eventos tanto de acción como de selección,
se utiliza la instrucción extends seguida del identificador de la clase e implementa las interfaces para
escuchar eventos a continuación mediante la instrucción implements seguida los identificadores de las
respectivas clases.
Cuando se trata de un componente tipo comando (Button y MenuItem) se debe especificar una cadena
identificadora del componente mediante el método setActionCommand(), la cual se incluirá en los eventos
ActionEvent generados por los componentes. Además se debe agregar el componente a la lista del
administrador de eventos mediante el método addActionListener().
cmdCalcular.setActionCommand("Calcular");
cmdCalcular.addActionListener(this);
if(chkNal.getState())
intTarifa=intDestinoNal[cmbTarifa.getSelectedIndex()];
if(chkInternal.getState())
intTarifa=intDestinoInternal[cmbTarifa.getSelectedIndex()];
double dblDescuento1=1-dblDescuento[cmbHora.getSelectedIndex()]/100;
double dblValor=dblDuracion*intTarifa*dblDescuento1;
lblValor.setText("$ "+Double.toString(dblValor));
}
}
Cuando se trata de un componente tipo selección (Choice, List y Checkbox) se debe agregar el componente
a la lista del administrador de eventos mediante el método addItemListener().
chkNal.addItemListener(this);
chkInternal.addItemListener(this);
lblValorTarifa.setText("$"+Integer.toString(intDestinoNal[cmbTarifa.getSelectedIndex()]));
/* Es una tarifa Internacional */
if(chkInternal.getState())
lblValorTarifa.setText("$"+Integer.toString(intDestinoInternal[cmbTarifa.getSelectedIndex()]));
}
/* Se hizo una selección en la lista desplegable de Horarios */
if(e.getItemSelectable()==cmbHora){
lblDescuento.setText(Double.toString(dblDescuento[cmbHora.getSelectedIndex()])+"
%");
}
}
Para saber si un botón de radio ha sido seleccionado, se utiliza el método getState() de Checkbox.
Para saber que opción ha sido escogida de una lista desplegable se utiliza el método getSelectedIndex() de
Choice.
15
Instituto Tecnológico Metropolitano
La clase Frame representa una ventana de aplicación de nivel superior, opcionalmente redimensionable, con
una barra de título y otras decoraciones que tienen las ventanas dependientes de plataforma (como las que
utiliza el sistema operativo MS Windows).
Método Descripción
setTitle (String titulo) Especifica el título para la ventana
setMenuBar Especifica un barra de menú
setIconImage Especifica un icono para la ventana
setCursor Especifica un cursor
pack() Inicia la administración del diseño de la ventana para ajustar el
tamaño al contenido inicial.
Show() Hace que aparezca el trazado de la ventana
dispose() Retira la ventana y libera los recursos del sistema para dicha ventana.
Para el manejo de los menús de barras, Java dispone de las siguientes clases:
Clase Descripción
MenuBar Esta clase representa una barra de menú. El método add() agrega objetos de la clase Menu a
la barra de menú, mientras que setHelpMenu() agrega un menú Help (Ayuda) en una
ubicación reservada de la barra de menú. Un objeto MenuBar se puede desplegar dentro de un
Frame al pasarlo como parámetro del método setMenuBar().
Menu Esta clase representa un panel de menú descendente que aparece dentro de un MenuBar.
Cada Menu tiene una etiqueta que aparece en el MenuBar y puede opcionalmente ser un
menú. Los métodos add() y addSeparator() agregan elementos individuales a Menu.
MenuItem Esta clase encapsula un elemento de menú con una etiqueta textual específica. Un MenuItem
se puede agregar a un panel de menú con el método Menu.add() . El método disable() hace
que un elemento no sea seleccionable; esto se puede usar para “aclarar” un elemento del
menú cuando el comando que éste represente no sea válido en el contexto en cuestión. El
método enable() hace que un elemento sea seleccionable otra vez. El método
addActionCommand() permite especificar una cadena identificadora de una acción para que
esté incluida en los eventos ActionEvent generados por el elemento de menú.
La siguiente aplicación consiste en una ventana que incluye un menú con las acciones necesarias para
consultar y actualizar información de unas elecciones. El código correspondiente a los eventos de dichas
acciones no se incluye aquí, ya que hacen parte del tema de acceso a bases de datos.
16
Instituto Tecnológico Metropolitano
Esta aplicación es una herencia de la clase Frame que implementa a ActionListener ya que tendrá eventos
de acción (Los comandos del menú). En ella se instancia un objeto MenuBar y un objeto Menu el cual
contendrá varios objetos MenuItem para cada una de las opciones.
La aplicación se instancia en el método main() utilizando un método constructor (Elecciones()). Este método
constructor contiene las instrucciones necesarias para definir el estado inicial de la ventana, lo cual
comprende la construcción del menú. Para ello se utilizan adicionalmente dos vectores que almacenan las
etiquetas y las acciones, y con base en ellos se instancia los objetos MenuItem y las respectivas acciones
asociadas.
Para que la aplicación ejecute los eventos de acción se incluye el método actionPerformed() en el cual va el
código de respuesta a cada acción.
import java.awt.*;
import java.awt.event.*;
for(int i=0;i<etiquetas.length;i++)
{
MenuItem mi=new MenuItem(etiquetas[i]); //Instanciar una opción del menu
mnuArchivo.add(mi); //Agregarlo al menu 'Archivo'
mi.setActionCommand(comandos[i]); //Definir el comando para la accion
mi.addActionListener(this); //Agregarlo el escuchador de eventos
}
this.pack(); //Ajustar la ventana
this.show();
/* Eventos */
public void actionPerformed(ActionEvent e)
{
String comando=e.getActionCommand(); //Evento activado
if (comando.equals("Mostrar"))
{
}
else if (comando.equals("Agregar"))
{
}
else if (comando.equals("Modificar"))
{
}
else if (comando.equals("Eliminar"))
{
}
else if (comando.equals("Salir")) System.exit(0);
}
}
Debido a que esta clase ofrece un acceso aleatorio a los archivos (en lugar de ser secuencial) no es una
subclase de InputStream ni de OutputStream (clases encargadas de las entradas y salidas estándar). Por lo
tanto, RandomAccessFile proporciona métodos completamente independientes para leer y escribir datos.
El método seek() ofrece un acceso aleatorio al archivo; se usa para seleccionar la posición en el archivo a
partir de la cual o en la cual deben leerse o escribirse los datos.
El método length() permite conocer la longitud del archivo, y se considera la posición final del archivo para
lectura.
Cuando se desea abrir un archivo, se utiliza el método constructor el cual tiene dos argumentos de entrada:
• Un String con el nombre del archivo
• Un String con el modo como será abierto el archivo: “r” para lectura, “rw” para lectura y escritura.
Para leer los datos se ofrecen métodos que obtienen datos primitivos producto de la lectura, así:
Método Descripción
readBoolean() Lee un valor booleano
readByte() Lee un byte
readChar() Lee un carácter
readDouble() Lee un número de tipo double
18
Instituto Tecnológico Metropolitano
De igual forma, existen métodos para guardar datos en el archivo por cada tipo de dato primitivo:
Método Descripción
writeBoolean() Guarda un valor booleano
writeByte() Guarda un byte
writeChar() Guarda un carácter
writeDouble() Guarda un número de tipo double
writeFloat() Guarda un número de tipo float
writeInt() Guarda un número de tipo int
writeBytes() Guarda un String
writeLong() Guarda un número de tipo long
Para comprender el uso de esta clase y sus métodos, se plantea un ejercicio de una aplicación en Java que
administre el directorio telefónico de un usuario. Los datos quedan almacenados en un archivo plano
llamado “Directorio.txt”. Estos comprenden el nombre, la dirección, el teléfono y la fecha de cumpleaños.
En ella se incluyen todos los comandos para administrar el directorio telefónico tales como:
• Guardar cambios realizados.
• Agregar un nuevo registro
• Eliminar un registro
19
Instituto Tecnológico Metropolitano
import java.awt.*;
import java.awt.event.*;
import java.io.*;
add(lblNom);add(txtNom);
add(lblTel);add(txtTel);
20
Instituto Tecnológico Metropolitano
add(lblDir);add(txtDir);
add(lblCum);add(txtCum);
add(btnPri);add(btnAnt);
add(btnSig);add(btnUlt);
add(lblMen);
21
Instituto Tecnológico Metropolitano
if (opcion.equals("Salir")) System.exit(0);
else if (opcion.equals("Anterior")) anterior();
else if (opcion.equals("Siguiente")) siguiente();
else if (opcion.equals("Primero")) primero();
else if (opcion.equals("Ultimo")) ultimo();
else if (opcion.equals("Guardar")) guardar();
else if (opcion.equals("Agregar")) agregar();
else if (opcion.equals("Eliminar")) eliminar();
}
public void siguiente()
{
if (posicion<tLineas && tLineas>0)
{
posicion++;mostrar();
}
else lblMen.setText("Estamos al final");
}
public void anterior()
{
if (posicion>1)
{
posicion--;mostrar();
}
else lblMen.setText("Estamos al inicio");
}
public void primero()
{
if (tLineas>0)
{
posicion=1;mostrar();
}
else lblMen.setText("No hay datos");
}
public void ultimo()
{
if (tLineas>0)
{
posicion=tLineas;mostrar();
}
else lblMen.setText("No hay datos");
}
public void mostrar()
{
txtNom.setText(nombres[posicion]);
txtTel.setText(telefonos[posicion]);
txtDir.setText(direcciones[posicion]);
txtCum.setText(cumpleanos[posicion]);
}
public void guardar()
{
try {
// Abre el archivo
RandomAccessFile directorio=new RandomAccessFile(archivo,"rw");
//Recorre el vector y lo lleva al archivo
for(int i=1;i<=tLineas;i++)
{
directorio.writeBytes(nombres[i]+"\n");
directorio.writeBytes(telefonos[i]+"\n");
directorio.writeBytes(direcciones[i]+"\n");
directorio.writeBytes(cumpleanos[i]+"\n");
}
22
Instituto Tecnológico Metropolitano
directorio.close();
}
catch (IOException e){System.out.println(e);} //Si sucede un error
}
public void agregar()
{
if(tLineas<max)
{
tLineas++;
nombres[tLineas]="";
telefonos[tLineas]="";
direcciones[tLineas]="";
cumpleanos[tLineas]="";
posicion=tLineas;mostrar();
lblMen.setText("Nuevo registro");
}
else lblMen.setText("Supera el número máximo de registros");
}
public void eliminar()
{
if (tLineas>0)
{
if(posicion==tLineas) posicion--;
for(int i=posicion;i<tLineas;i++)
{
nombres[i]=nombres[i+1];
telefonos[i]=telefonos[i+1];
direcciones[i]=direcciones[i+1];
cumpleanos[i]=cumpleanos[i+1];
}
tLineas--;
if(tLineas>0) mostrar();
else
{
agregar();
}
}
}
public void guardarVector()
{
if (posicion>0)
{
nombres[posicion]=txtNom.getText();
telefonos[posicion]=txtTel.getText();
direcciones[posicion]=txtDir.getText();
cumpleanos[posicion]=txtCum.getText();
}
}
public void ordenar()
{
for(int i=1;i<tLineas;i++)
for(int j=i+1;j<=tLineas;j++)
if(nombres[i].compareTo(nombres[j])>1)
{
String strT=nombres[i];nombres[i]=nombres[j];nombres[j]=strT;
strT=telefonos[i];telefonos[i]=telefonos[j];telefonos[j]=strT;
strT=direcciones[i];direcciones[i]=direcciones[j];direcciones[j]=strT;
strT=cumpleanos[i];cumpleanos[i]=cumpleanos[j];cumpleanos[j]=strT;
}
}
}
23
Instituto Tecnológico Metropolitano
2. Elaborar una ventana que liste los países del continente americano y que permita listar los respectivos
estados o departamentos del país elegido. Cuando se elija un estado, debe mostrar su respectiva
capital. La información viene en un archivo de texto.
24