⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 java9.htm

📁 E-books about Java Programing in Spanish
💻 HTM
字号:
<HTML>
<HEAD>
<TITLE>Java desde Cero</TITLE>
</HEAD>
<BODY background=/iconos/1.gif  TEXT=000000 LINK=FF0000 VLINK=A62A2A>

<H1>Completando la ventana<BR>
</H1>
<P>
Vamos a empezar por completar nuestro m&eacute;todo <FONT FACE="Arial">ActualizaBoton</FONT>,
que modificar&aacute; el texto del bot&oacute;n <FONT FACE="Arial">ok</FONT>
a medida que seleccionemos las ciudades y la fecha:<BR>
<PRE>
<FONT SIZE=2>void ActualizaBoton() {
    StringBuffer b = new StringBuffer(&quot;Viaje: de &quot;);
    if (cs.getDescription() != null) b.append(cs.getDescription());
    else b.append(&quot;?&quot;);
    b.append(&quot; a &quot;);
    if (cl.getDescription() != null) b.append(cl.getDescription());
    else b.append(&quot;?&quot;);
    b.append(&quot; el &quot;);
    if (dp.getDescription() != null) b.append(dp.getDescription());
    else b.append(&quot;?/?/?&quot;);
    ok.setLabel(b.toString());
  }<BR>
</FONT>
</PRE>
<P>
Nuestro m&eacute;todo comienza por crear un <FONT FACE="Arial">StringBuffer</FONT>
con las palabras &quot;Viaje: de &quot;, y va agregando el resto:
<UL>
<LI>la ciudad de partida, llamando al m&eacute;todo <FONT FACE="Arial">getDescription</FONT>
de <FONT FACE="Arial">cs</FONT> (ciudad de salida)
<LI>el texto constante &quot; a &quot;
<LI>la ciudad de llegada, llamando al m&eacute;todo <FONT FACE="Arial">getDescription</FONT>
de <FONT FACE="Arial">cl</FONT> (ciudad de llegada)
<LI>el texto constante &quot; el &quot;
<LI>la fecha seleccionada, llamando al m&eacute;todo <FONT FACE="Arial">getDescription</FONT>
de <FONT FACE="Arial">dp</FONT> (d&iacute;a de partida)
</UL>
<P>
Si en cualquier caso recibe un string nulo, pone un signo de pregunta
(o ?/?/? para la fecha).
<P>
El m&eacute;todo <FONT FACE="Arial">setLabel</FONT>, sobre el
objeto <FONT FACE="Arial">ok</FONT> de tipo <I>Label</I>, modifica
la &quot;etiqueta&quot; del bot&oacute;n.
<P>
Realmente nos devuelven <FONT FACE="Arial">null</FONT> los m&eacute;todos
que llamamos si no hay selecci&oacute;n hecha?
<P>
Veamos:<BR>
<PRE>
<FONT SIZE=2>class SelecPueblo extends Panel {
private List	listaPueblos;
............................
public String getDescription() {
return listaPueblos.getSelectedItem();
}
}<BR>
</FONT>
</PRE>
<P>
El m&eacute;todo <FONT FACE="Arial">getSelectedItem</FONT> de
la clase <I>List</I> devuelve <FONT FACE="Arial">null</FONT> si
no hay &iacute;tems seleccionados, as&iacute; que ac&aacute; andamos
bien. En cuanto a la clase <FONT FACE="Arial">DiaPartida</FONT>,
de entrada inicializa el valor del texto en la fecha actual, as&iacute;
que aqu&iacute; no se dar&iacute;a nunca este caso... Aunque al
crear el objeto <FONT FACE="Arial">Ventana8</FONT> estamos poniendo
un texto fijo en el bot&oacute;n, y no el que devuelve el objeto
<FONT FACE="Arial">dp</FONT>.
<P>
Ser&iacute;a mejor, para ser m&aacute;s consistente, modificar
el constructor de <FONT FACE="Arial">Ventana8</FONT> para que
arme el texto mediante el m&eacute;todo <FONT FACE="Arial">ActualizaBot&oacute;n</FONT>:
<BR>
<PRE>
<FONT SIZE=2>Ventana8 (String titulo, boolean enApplet) {
........................................
<B>	ok = new Button(&quot;cualquiera&quot;);
	ActualizaBoton();
	add(&quot;South&quot;,ok);
</B>	pack();
	show();
  }<BR>
</FONT>
</PRE>
<P>
Esto ya se ve mejor! Y de paso probamos el m&eacute;todo...<BR>
<H3>Un poquito de actividad</H3>
<P>
Ahora s&iacute;, pasemos a completar nuestro manejador de eventos:
<BR>
<PRE>
<FONT SIZE=2>public boolean handleEvent(Event e) {
	if (e.id == Event.WINDOW_DESTROY) {
		if (enApplet) dispose();
		else System.exit(0);
	}
<B>if ( (e.target==dp)||(e.target==cs)||(e.target==cl) )
ActualizaBoton();
if (e.target==ok)
Activar();
}
</B>return super.handleEvent(e);
}<BR>
</FONT>
</PRE>
<P>
Simplemente, si detectamos un evento sobre alguno de nuestros
paneles actualizamos el texto del bot&oacute;n; y si se presiona
dicho bot&oacute;n llamamos al m&eacute;todo Activar que se supone
que va a tomar los datos de la base de datos, indicarnos servicios
disponibles, etc.
<P>
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&aacute;quina lenta). Adem&aacute;s,
si hacen click sobre el bot&oacute;n <B>Hoy</B> o <B>Ma&ntilde;ana</B>
<I>sin</I> mover el mouse, el texto del bot&oacute;n <FONT FACE="Arial">ok</FONT>
no se actualiza ya que el evento va dirigido al bot&oacute;n presionado
y no al panel.
<P>
Una forma de filtrar s&oacute;lo los eventos que nos interesan
ser&iacute;a usar, por ejemplo:<BR>
<PRE>
<FONT SIZE=2>if ((e.target=cs.listaPueblos) &amp;&amp; (e.id==Event.LIST_SELECT)) ActualizaBoton();
<BR>
</FONT>
</PRE>
<P>
que est&aacute; dirigida a la <I>lista</I> y no al <I>panel</I>
en general, y tiene en cuenta el tipo de evento.
<P>
Lamentablemente, <FONT FACE="Arial">listaPueblos</FONT> es privada
dentro de la clase <FONT FACE="Arial">SelecPueblo</FONT> y por
lo tanto dentro de <FONT FACE="Arial">cs</FONT>. Pero es mejor
as&iacute;, porque declararla p&uacute;blica y leerla desde afuera
ser&iacute;a bastante sucio (as&iacute; como la leemos podr&iacute;amos
escribirla).
<P>
Hay varias formas de mejorar esto sin cometer la torpeza de declarar
p&uacute;blica a <FONT FACE="Arial">listaPueblos</FONT>. Una posibilidad
es verificar, usando <FONT FACE="Arial">cs.getDescription()</FONT>,
si el texto cambi&oacute; (y s&oacute;lo en ese caso modificar
el texto del bot&oacute;n).
<P>
Otra, es hacer que los objetos de la clase <FONT FACE="Arial">SelecPueblo</FONT>
pasen a sus padres cualquier evento sobre ellos, o mejor solamente
la selecci&oacute;n de un elemento de la lista; para eso basta
agregar a la clase <FONT FACE="Arial">SelecPueblo</FONT>:<BR>
<PRE>
<FONT SIZE=2>public boolean handleEvent(Event e) {
if ((e.target==listaPueblos) &amp;&amp; (e.id==Event.LIST_SELECT)) {
e.target=this;
}
return super.handleEvent(e);
}<BR>
</FONT>
</PRE>
<P>
En resumen: si el evento en el panel es una selecci&oacute;n de
la lista (tanto con mouse como moviendo la selecci&oacute;n con
las flechas), cambio el <FONT FACE="Arial">target</FONT> del evento
para que indique el <I>panel</I> (y no la <I>lista</I>); si no,
lo paso a la clase antecesora.
<P>
Lo mismo podemos hacer con <FONT FACE="Arial">handleEvent</FONT>
para la clase <FONT FACE="Arial">DiaPartida</FONT>:<BR>
<PRE>
<FONT SIZE=2>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);
}<BR>
</FONT>
</PRE>
<P>
Esto no anda como esperar&iacute;amos! El campo de texto no se
comporta muy bien...
<P>
Esto es porque el c&oacute;digo dependiente de la plataforma procesa
los eventos de mouse <I>antes</I> de llamar a <FONT FACE="Arial">handleEvent</FONT>,
pero procesa los de teclado <I>despu&eacute;s</I> de llamar a
<FONT FACE="Arial">handleEvent</FONT>.
<P>
Lo que significa que, en el caso del campo de texto, <FONT FACE="Arial">handleEvent</FONT>
(y por lo tanto <FONT FACE="Arial">ActualizaBot&oacute;n</FONT>)
se llama <I>antes</I> de modificar el texto!
<P>
Para corregir esto, deber&iacute;amos procesar nosotros las teclas
presionadas (lo que podr&iacute;amos aprovechar para verificar
que se presiona una tecla v&aacute;lida).
<P>
Cuidado! En futuras versiones de Java podr&iacute;a implementarse
el mismo comportamiento para el mouse, y por lo tanto tendr&iacute;amos
que repensar la estrategia.
<P>
Para colmo, s&oacute;lo los eventos que la plataforma env&iacute;a
llegan a Java; por ejemplo, Motif no env&iacute;a eventos de movimiento
de mouse dentro de un campo de texto... lo que significa que nunca
podr&iacute;amos capturar ese tipo de eventos. S&oacute;lo el
componente <B>Canvas</B> pasa todos los eventos.
<P>
Para simplificar, s&oacute;lo actualizaremos el texto del bot&oacute;n
cuando se presiona <B>Enter</B> (Event.key=10):<BR>
<PRE>
<FONT SIZE=2>if ((e.target == elDia)&amp;&amp;(e.id==Event.KEY_PRESS)) {
	if (e.key==10) e.target=this;
}<BR>
</FONT>
</PRE>
<P>
Ahora debemos modificar el m&eacute;todo <FONT FACE="Arial">handleEvent</FONT>
en nuestra clase <FONT FACE="Arial">Ventana8</FONT> para que soporte
todos estos eventos:<BR>
<PRE>
<FONT SIZE=2>public boolean handleEvent(Event e) {
	if (e.id == Event.WINDOW_DESTROY) {
		if (enApplet) dispose();
		else System.exit(0);
	}
	if ( ((e.target==dp)&amp;&amp;((e.id==Event.ACTION_EVENT)||(e.id==Event.KEY_PRESS)))
||((e.target==cs)&amp;&amp;(e.id==Event.LIST_SELECT))
||((e.target==cl)&amp;&amp;(e.id==Event.LIST_SELECT)) )
			ActualizaBoton();
	if (e.target==ok)
Activar();
	return super.handleEvent(e);
}<BR>
</FONT>
</PRE>
<P>
Obviamente, procesar todas las teclas nosotros ser&iacute;a bastante
m&aacute;s complicado... de todos modos, el m&eacute;todo en <FONT FACE="Arial">DiaPartida</FONT>
ser&iacute;a m&aacute;s o menos as&iacute;:<BR>
<PRE>
<FONT SIZE=2>if ((e.target == elDia)&amp;&amp;(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: <B>getParent().deliverEvent(e)
</B>	// 6- evitar proceso posterior del evento mediante: <B>result(true)
</B>}
</FONT>
</PRE>
<P>
Me ahorro explicar estos dos &uacute;ltimos pasos; se complica
bastante todo porque hay que manejar la posici&oacute;n del cursor
dentro del campo de texto, etc&eacute;tera. Con lo que hicimos
es bastante... creo!
<H3>Y para terminar...</H3>
<P>
Bueno, s&oacute;lo nos queda por definir el m&eacute;todo <FONT FACE="Arial">Activar()</FONT>.
Primero vamos a llamar a <FONT FACE="Arial">ActualizaBoton()</FONT>
por si alguien lo &uacute;ltimo que hizo fue entrar un texto sin
presionar <B>Enter</B>, y dejo para otro d&iacute;a m&aacute;s
tranquilo consultar un archivo o base de datos con lo que vamos
a mostrar al usuario de nuestro programa.
<P>
Por ahora simplemente vamos a mostrar una ventana con la selecci&oacute;n
y un lindo bot&oacute;n de OK.
<P>
Primero vamos a hacer una muy peque&ntilde;a modificaci&oacute;n
a <FONT FACE="Arial">ActualizaBoton()</FONT> para que nos devuelva
el valor del texto del bot&oacute;n (para no calcularlo de nuevo):
<BR>
<PRE>
<FONT SIZE=2>String ActualizaBoton() {
    StringBuffer b = new StringBuffer(&quot;Viaje: de &quot;);
..............................................
    ok.setLabel(b.toString());
  }<BR>
</FONT>
</PRE>
<P>
Y ahora vamos a definir nuestro m&eacute;todo, teniendo en cuenta
que nuestro bot&oacute;n s&oacute;lo actuar&aacute; si se han
entrado todos los datos:<BR>
<PRE>
<FONT SIZE=2>void Activar() {
if ( (cs.getDescription() != null) &amp;&amp; (cl.getDescription() != null) )
// tambi&eacute;n podr&iacute;amos verificar que la fecha sea v&aacute;lida aqu&iacute;
Result8 resultado = new Result8(&quot;Resultado&quot;,ActualizaBoton());
else ok.setLabel(&quot;Especificaci&oacute;n incompleta!&quot;);
  }<BR>
</FONT>
</PRE>
<P>
S&oacute;lo nos falta definir una sencilla clase <FONT FACE="Arial">Result8</FONT>
para nuestra ventanita resultado:<BR>
<PRE>
<FONT SIZE=2>// archivo Result8.java, compilar con javac Result8.java
import java.awt.*;

class Result8 extends Frame {

Button	r_ok;

Result8 (String titulo, String texto) {	// constructor
super(titulo);
Label r_lbl = new Label(texto);
r_ok = new Button(&quot;Ok&quot;);
	add(&quot;Center&quot;, r_lbl);
		add(&quot;South&quot;, r_ok);
	pack();
		show();
}

public boolean handleEvent(Event e) {
if ((e.id == Event.WINDOW_DESTROY)||(e.target==r_ok))
dispose();	// cierra esta ventana pero no la aplicaci&oacute;n
	return super.handleEvent(e);
}
}<BR>
</FONT>
</PRE>
<P>
Noten que us&eacute; <FONT FACE="Arial">dispose</FONT> y no <FONT FACE="Arial">System.exit</FONT>!
Esto permite cerrar s&oacute;lo la ventana de resultado, y seguir
usando la aplicaci&oacute;n hasta que se nos ocurra cerrarla mediante
meta-F4, alt-F4, el men&uacute; de sistema de la ventana, la cruz
de Windows 95 o lo que le resulte a su sistema operativo.<BR>
<H3>Finale con tutto</H3>
<P>
Espero que se haya entendido! Esta aplicaci&oacute;n cost&oacute;
bastante pero en el camino hemos tenido oportunidad de aprender
unas cuantas cosas... Si logran juntar todo el c&oacute;digo y
generar las varias clases que definimos, todo tiene que andar
sobre rieles e independientemente de la plataforma.
<P>
Si no... av&iacute;senme, y subo tambi&eacute;n los fuentes o
las clases.<BR>
<P>
Por las dudas, pueden probar esta aplicaci&oacute;n como applet
cargando:<BR>
<PRE>
<FONT SIZE=2>http://www.amarillas.com/rock/java/Ejemplo8.htm<BR>
<BR>
</FONT>
</PRE>
<P>
Y basta por hoy. En el cap&iacute;tulo 10 vamos a empezar a manejar
el I/O de Java.
<P>
Todav&iacute;a nos queda mucho por ver! (Y no hemos terminado
con el AWT...)<BR>
<BR>
<P>
Jorge Bourdette
<P>
<A HREF="mailto:jpb@amarillas.com" >jpb@amarillas.com</A>
</BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -