Ahora sí, pasemos a completar nuestro manejador de eventos:
public boolean handleEvent(Event e) {
if (e.id
Event.WINDOW_DESTROY) {
if (enApplet) dispose();
else System.exit(0);
}
if ( (e.target
dp)||(e.targetcs)||(e.target
cl) )
ActualizaBoton();
if (e.targetok)
Activar();
}
return super.handleEvent(e);
}
Simplemente, si detectamos un evento sobre alguno de nuestros paneles actualizamos el texto del botón; y si se presiona dicho botón llamamos al método Activar que se supone que va a tomar los datos de la base de datos, indicarnos servicios disponibles, etc.
Algo importante a notar es que el simple hecho de mover el mouse sobre uno de los paneles ya llama a ActualizaBoton (se nota porque titila el texto, sobre todo en una máquina lenta). Además, si hacen click sobre el botón
Hoy o
Mañana sin mover el mouse, el texto del botón ok no se actualiza ya que el evento va dirigido al botón presionado y no al panel.
Una forma de filtrar sólo los eventos que nos interesan sería usar, por ejemplo:
if ((e.target=cs.listaPueblos) && (e.id
Event.LIST_SELECT)) ActualizaBoton();
que está dirigida a la
lista y no al
panel en general, y tiene en cuenta el tipo de evento.
Lamentablemente, listaPueblos es privada dentro de la clase SelecPueblo y por lo tanto dentro de cs. Pero es mejor así, porque declararla pública y leerla desde afuera sería bastante sucio (así como la leemos podríamos escribirla).
Hay varias formas de mejorar esto sin cometer la torpeza de declarar pública a listaPueblos. Una posibilidad es verificar, usando cs.getDescription(), si el texto cambió (y sólo en ese caso modificar el texto del botón).
Otra, es hacer que los objetos de la clase SelecPueblo pasen a sus padres cualquier evento sobre ellos, o mejor solamente la selección de un elemento de la lista; para eso basta agregar a la clase SelecPueblo:
public boolean handleEvent(Event e) {
if ((e.target
listaPueblos) && (e.id
Event.LIST_SELECT)) {
e.target=this;
}
return super.handleEvent(e);
}
En resumen: si el evento en el panel es una selección de la lista (tanto con mouse como moviendo la selección con las flechas), cambio el target del evento para que indique el
panel (y no la
lista); si no, lo paso a la clase antecesora.
Lo mismo podemos hacer con handleEvent para la clase DiaPartida:
public boolean handleEvent (Event e) {
if (e.target
hoy) {
elDia.setText(GetHoy());
e.target=this;
}
if (e.target
diasiguiente) {
elDia.setText(GetManana());
e.target=this;
}
if (e.target
elDia) {
e.target=this;
}
return super.handleEvent(e);
}
Esto no anda como esperaríamos! El campo de texto no se comporta muy bien...
Esto es porque el código dependiente de la plataforma procesa los eventos de mouse antes de llamar a handleEvent, pero procesa los de teclado después de llamar a handleEvent.
Lo que significa que, en el caso del campo de texto, handleEvent (y por lo tanto ActualizaBotón) se llama antes de modificar el texto!
Para corregir esto, deberíamos procesar nosotros las teclas presionadas (lo que podríamos aprovechar para verificar que se presiona una tecla válida).
Cuidado! En futuras versiones de Java podría implementarse el mismo comportamiento para el mouse, y por lo tanto tendríamos que repensar la estrategia.
Para colmo, sólo los eventos que la plataforma envía llegan a Java; por ejemplo, Motif no envía eventos de movimiento de mouse dentro de un campo de texto... lo que significa que nunca podríamos capturar ese tipo de eventos. Sólo el componente Canvas pasa todos los eventos.
Para simplificar, sólo actualizaremos el texto del botón cuando se presiona Enter (Event.key=10):
if ((e.target
elDia)&&(e.id
Event.KEY_PRESS)) {
if (e.key
10) e.target=this;
}
Ahora debemos modificar el método handleEvent en nuestra clase Ventana8 para que soporte todos estos eventos:
public boolean handleEvent(Event e) {
if (e.id
Event.WINDOW_DESTROY) {
if (enApplet) dispose();
else System.exit(0);
}
if ( ((e.target
dp)&&((e.id
Event.ACTION_EVENT)||(e.id
Event.KEY_PRESS)))
||((e.targetcs)&&(e.id
Event.LIST_SELECT))
||((e.targetcl)&&(e.id
Event.LIST_SELECT)) )
Activar();
return super.handleEvent(e);
}
Obviamente, procesar todas las teclas nosotros sería bastante más complicado... de todos modos, el método en DiaPartida sería más o menos así:
if ((e.target
elDia)&&(e.id
Event.KEY_PRESS)) {
1- leer el contenido del campo con: elDia.getText()
2- modificarlo de acuerdo a la tecla presionada: e.key
3- poner el resultado en el campo con: elDia.setText(texto)
4- modificar el objeto del evento al panel con: e.target=this;
5- enviar el evento al objeto padre (no la clase padre),
en este caso Ventana8, mediante: getParent().deliverEvent(e)
6- evitar proceso posterior del evento mediante: result(true)
}
Me ahorro explicar estos dos últimos pasos; se complica bastante todo porque hay que manejar la posición del cursor dentro del campo de texto, etcétera. Con lo que hicimos es bastante... creo!