?? java12.htm
字號:
<HTML>
<HEAD>
<META NAME="GENERATOR" CONTENT="Internet Assistant for Microsoft Word 2.0z">
<TITLE>Untitled</TITLE>
<BODY background=/iconos/1.gif TEXT=000000 LINK=FF0000 VLINK=A62A2A>
</HEAD>
<BODY>
<H1>DibuJava<BR>
</H1>
<P>
Además de los componentes estándar (botones, listas,
etc.), hay un componente para dibujo "libre" que nos
permite implementar cualquier otro tipo de control: la clase <B>Canvas</B>.
Típicamente se usa para dibujar, y corresponde a una zona
rectangular dentro de una ventana.
<P>
La clase en sí no hace prácticamente nada; el programador
debe definir una subclase de <B>Canvas</B> a la que el AWT le
envía todos los eventos de mouse y teclado. Redefiniendo
los métodos <B>gotFocus, lostFocus, keyDown, keyUp, mouseEnter,
mouseExit, mouseMove, mouseDrag, mouseDown</B> y <B>mouseUp</B>,
el programador puede hacer lo que se le ocurra dentro de ese rectángulo.
Vamos a hacer uso de un <B>Canvas</B> para generar un applet donde
habrá una zona rectangular dentro de la que, haciendo click
con el mouse y moviéndolo sin soltar el botón, dibujaremos
un rectángulo dinámicamente.
<P>
Esto nos permitirá ver cómo usar un <B>Canvas</B>
para dibujar, capturar eventos, etc. El borde tiembla un poco
al redibujar, pero ya veremos cómo evitar eso.
<H2>Canvas en acción</H2>
<P>
Primero vamos a poner, como ya se está haciendo costumbre,
el código del applet (Recordar que debe cargarse desde
una página html para verlo! Aquí no creamos ninguna
ventana y no podremos verlo como aplicación standalone)
y luego intentaremos explicar cómo funciona.<BR>
<PRE>
<FONT SIZE=2>import java.awt.*;
import java.applet.Applet;
public class Ejemplo15 extends Applet {
public void init() {
Label label = new Label("Pique y arrastre con el mouse!");
miCanvas zonaDib = new miCanvas();
zonaDib.resize(new Dimension (200,200));
add("North", label);
add("Center", zonaDib);
resize(300,250);
}
}
class miCanvas extends Canvas {
Rectangle rectActual;
public boolean mouseDown(Event e, int x, int y) {
rectActual = new Rectangle(x, y, 0, 0);
repaint();
return false;
}
public boolean mouseDrag(Event e, int x, int y) {
rectActual.resize(x-rectActual.x, y-rectActual.y);
repaint();
return false;
}
public boolean mouseUp(Event e, int x, int y) {
rectActual.resize(x-rectActual.x, y-rectActual.y);
repaint();
return false;
}
public void paint(Graphics g) {
Dimension d = size();
g.setColor(Color.red);
g.drawRect(0, 0, d.width-1, d.height-1);
g.setColor(Color.blue);
if (rectActual != null) {
Rectangle box = cortarRect(rectActual, d);
g.drawRect(box.x, box.y, box.width-1, box.height-1);
}
}
Rectangle cortarRect(Rectangle miRect, Dimension areaDib) {
int x = miRect.x;
int y = miRect.y;
int ancho = miRect.width;
int alto = miRect.height;
if (ancho < 0) {
ancho = -ancho;
x = x - ancho + 1;
if (x < 0) {
ancho += x;
x = 0;
}
}
if (alto < 0) {
alto = -alto;
y = y - alto + 1;
if (y < 0) {
alto += y;
y = 0;
}
}
if ((x + ancho) > areaDib.width) {
ancho = areaDib.width - x;
}
if ((y + alto) > areaDib.height) {
alto = areaDib.height - y;
}
return new Rectangle(x, y, ancho, alto);
}
}<BR>
</FONT>
</PRE>
<H2>El applet-container</H2>
<P>
En primer lugar hemos tenido en cuenta que un <B>Applet</B> es
un <B>Panel</B>, y por lo tanto también un <B>Container</B>,
así que en lugar de crear una ventana aparte simplemente
le agregamos dos componentes: un <B>Label</B> y un <B>Canvas</B>.
<BR>
<PRE>
<FONT SIZE=2> zonaDib.resize(new Dimension (200,200));
add("North", label);
add("Center", zonaDib);
resize(300,250);<BR>
</FONT>
</PRE>
<P>
El método <FONT FACE="Arial">rezise</FONT>, sobre la clase
<FONT FACE="Arial">miCanvas</FONT>, nos permite redimensionar
el mismo al tamaño deseado. Igualmente, usamos <FONT FACE="Arial">resize</FONT>
sobre el applet para darle un tamaño adecuado. Si se modifica
el tamaño de la ventana en el appletviewer se observará
un comportamiento algo extraño en cuanto al posicionamiento
relativo del rectángulo y el cartel, pero para simplificar
esto bastará.<BR>
<H2>Nuestro Canvas a medida</H2>
<P>
Como no vamos a tomar ninguna acción especial al crear
el <FONT FACE="Arial">canvas</FONT>, no hemos definido el constructor
(se utiliza el constructor por defecto de la clase <FONT FACE="Arial">Canvas</FONT>).
<P>
Simplemente hemos redefinido algunos métodos para actuar
al presionar, arrastrar y soltar el mouse, para redibujar el área
de dibujo (<FONT FACE="Arial">canvas</FONT>) y para recortar el
rectángulo dibujado si nos vamos con el mouse fuera del
espacio que ocupa el <FONT FACE="Arial">canvas</FONT>.
<P>
La variable global <FONT FACE="Arial">rectActual</FONT>, de la
clase <FONT FACE="Arial">Rectangle</FONT>, contendrá las
coordenadas del rectángulo que estamos dibujando. El método
Paint se llama automáticamente cada vez que es necesario
redibujar el componente, o si llamamos explícitamente al
método <FONT FACE="Arial">repaint()</FONT>:<BR>
<PRE>
<FONT SIZE=2>public void paint(Graphics g) {
Dimension d = size();
g.setColor(Color.red);
g.drawRect(0, 0, d.width-1, d.height-1);
g.setColor(Color.blue);
if (rectActual != null) {
Rectangle box = cortarRect(rectActual, d);
g.drawRect(box.x, box.y, box.width-1, box.height-1);
}
}<BR>
</FONT>
</PRE>
<P>
En primer lugar le asignamos a una variable <FONT FACE="Arial">d</FONT>
el tamaño del <FONT FACE="Arial">canvas</FONT> usando el
método <FONT FACE="Arial">size()</FONT>, luego elegimos
un color (rojo) para dibujar un borde y dibujamos un rectángulo
del tamaño del componente:
<PRE>
<FONT SIZE=2> Dimension d = size();
g.setColor(Color.red);
g.drawRect(0, 0, d.width-1, d.height-1);<BR>
</FONT>
</PRE>
<P>
Dos atributos de la clase <FONT FACE="Arial">Dimension</FONT>,
<FONT FACE="Arial">width</FONT> y <FONT FACE="Arial">height</FONT>,
se han cargado con el tamaño del canvas y son los que usamos
para dar el tamaño del rectángulo.
<P>
Luego, si se está dibujando un rectángulo (<FONT FACE="Arial">rectActual
!= null</FONT>) simplemente lo recortamos (en caso de que hayamos
arrastrado el mouse fuera del canvas) y lo dibujamos.<BR>
<P>
El método que lo recorta a los límites del canvas,
<FONT FACE="Arial">cortarRect</FONT>, asigna a cuatro variables
las coordenadas del rectángulo (que se le pasaron como
parámetro <FONT FACE="Arial">miRect</FONT> al llamarlo):
<PRE>
<FONT SIZE=2> int x = miRect.x;
int y = miRect.y;
int ancho = miRect.width;
int alto = miRect.height;<BR>
</FONT>
</PRE>
<P>
Si el <FONT FACE="Arial">ancho</FONT> (o el <FONT FACE="Arial">alto</FONT>)
es negativo, simplemente lo cambia de signo y toma como coordenada
<FONT FACE="Arial">x</FONT> (<FONT FACE="Arial">y</FONT>) de origen
el otro vértice del rectángulo, que corresponderá
al <FONT FACE="Arial">x</FONT> que se pasó menos el <FONT FACE="Arial">ancho</FONT>
y más uno (recordar que el origen de coordenadas empieza
en cero y no en uno). Si este vértice está fuera
del canvas (<FONT FACE="Arial">x<0</FONT>), lo pone en cero
y le resta al ancho la parte recortada (notar que <FONT FACE="Arial">ancho+=x</FONT>,
como <FONT FACE="Arial">x</FONT> es negativo, es en realidad una
resta).
<PRE>
<FONT SIZE=2>if (ancho < 0) {
ancho = -ancho;
x = x - ancho + 1;
if (x < 0) {
ancho += x;
x = 0;
}
}<BR>
</FONT>
</PRE>
<P>
Si nos vamos del área de dibujo por la derecha (o por abajo),
simplemente le recortamos al ancho (<FONT FACE="Arial">alto</FONT>)
el exceso de modo que llegue hasta el borde del área de
dibujo (que también hemos pasado al método como
parámetro):
<PRE>
<FONT SIZE=2>if ((x + ancho) > areaDib.width) {
ancho = areaDib.width - x;</FONT>
</PRE>
<P>
<FONT SIZE=2>}<BR>
</FONT>
<P>
Sólo nos quedan por ver los métodos que responden
al mouse.
<P>
Cuando presionamos el mouse dentro del canvas, comenzamos la creación
de un nuevo rectángulo de ancho y alto cero que comienza
en el punto en que hemos presionado el mouse, y redibujamos el
canvas:
<PRE>
<FONT SIZE=2>public boolean mouseDown(Event e, int x, int y) {
rectActual = new Rectangle(x, y, 0, 0);
repaint();
return false;
}<BR>
</FONT>
</PRE>
<P>
Al mover el mouse, redimensionamos el rectángulo con ancho
<FONT FACE="Arial">x</FONT> menos el origen de dibujo (y alto
<FONT FACE="Arial">y</FONT> menos el origen de dibujo), y repintamos:
<PRE>
<FONT SIZE=2> public boolean mouseDrag(Event e, int x, int y) {
rectActual.resize(x-rectActual.x, y-rectActual.y);
repaint();
return false;
}<BR>
</FONT>
</PRE>
<P>
Finalmente, al soltar el mouse, redimensionamos como antes y redibujamos:
<PRE>
<FONT SIZE=2> public boolean mouseUp(Event e, int x, int y) {
rectActual.resize(x-rectActual.x, y-rectActual.y);
repaint();
return false;
}<BR>
</FONT>
</PRE>
<P>
Como no se toma ninguna medida para guardar el rectángulo
dibujado, al crear uno nuevo (reasignando <FONT FACE="Arial">rectActual</FONT>
a un nuevo rectángulo), el anterior se pierde.<BR>
<BR>
<P>
Bueno, para empezar a dibujar no está mal. Partes de este
código han sido tomadas de ejemplos del Tutorial de Java
del site de S<I>un</I>. Al final del curso haremos una lista de
bibliografía y sitios de interés para profundizar
en Java, pero por ahora nos falta bastante: algo más de
dibujo, manejo de excepciones, threads... Nos vemos el próximo
capítulo!<BR>
<BR>
<P>
Jorge Bourdette
<P>
<A HREF="jpb@amarillas.com" >jpb@amarillas.com</A><BR>
</BODY>
</HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -