El control Canvas (II)

prev.gif (997 bytes)chapter.gif (1105 bytes)home.gif (1232 bytes)next.gif (1211 bytes)

Sucesos (events)

Dibujar un punto pulsando el botón izquierdo del ratón

Dibujar "a mano alzada"


Dibujar un punto pulsando el botón izquierdo del ratón

disco.gif (1035 bytes)canvas3: CanvasApplet3.java, MiCanvas.java

Propósito

Volvemos a estudiar el ejemplo en el que se dibujaban pequeños círculos al pulsar el botón izquierdo del ratón, y se guardaban en memoria en un array. Ahora se trata de dibujar los puntos no en el applet sino en un control canvas.

Diseño

Crear el applet y establecer BorderLayout como gestor de diseño

Crear una clase MiCanvas derivada de Canvas

Crear un objeto canvas de la clase MiCanvas y situarlo en el centro (CENTER) de applet.

Respuesta a las acciones del usuario

En modo diseño (pestaña Design), seleccionamos el objeto canvas en el panel de componentes y en el panel Events situado a la derecha hacemos doble-clic sobre el editor asociado a mousePressed. JBuilder genera el código tal como se ha explicado en las páginas anteriores, y de la forma que se indica en el listado

Como vemos, se asocia el control canvas, donde se van a producir los sucesos relacionados con el ratón, con un objeto de una clase anómina que deriva de la clase MouseAdapter y que redefine la función mousePressed.

La función respuesta canvas_mousePressed, llama a la función dibujaPunto miembro de la clase MiCanvas y le pasa las coordendas del punto de la superficie del canvas donde se ha pulsado el botón izquierdo del ratón. La abscisa x, y la ordenada y del punto están encapsuladas en un objeto de la clase Point.

public class CanvasApplet3 extends Applet {
    MiCanvas canvas;
    BorderLayout borderLayout1 = new BorderLayout();

    public void init() {
        canvas=new MiCanvas();
        this.setLayout(borderLayout1);
        this.add(canvas, BorderLayout.CENTER);
        canvas.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                canvas_mousePressed(e);
            }
        });
    }

    void canvas_mousePressed(MouseEvent ev) {
        canvas.dibujaPunto(ev.getPoint());
    }

}

La definición de la clase que describe el canvas, MiCanvas es similar a la estudiada en ejemplos precedentes. El código de las funciones dibujaPunto y de la redefinición de paint, es similar al ejemplo estudiado dibujar los puntos y guardarlos en memoria.

Recordaremos que cuando el contexto gráfico g se obtiene mediante la función getGraphics es necesario liberar los recursos asociados a dicho contexto mediante llamada a la función dispose.

package canvas3;

import java.awt.*;
public class MiCanvas extends Canvas {
    final int MAXPUNTOS=20;
    Point puntos[]=new Point[MAXPUNTOS];
    int nPuntos=0;

  public MiCanvas() {
    setBackground(Color.white);
 }
 void dibujaPunto(Point p){
     Graphics g=getGraphics();
     g.setColor(Color.red);
     if(nPuntos<MAXPUNTOS){
        puntos[nPuntos]=p;
        nPuntos++;
     }
     g.fillOval(p.x-4, p.y-4, 8, 8);
     g.dispose();
 }

 public void paint(Graphics g){
     g.setColor(Color.blue);
     for(int i=0; i<nPuntos; i++){
        g.drawOval(puntos[i].x-4, puntos[i].y-4, 8, 8);
    }
 }
}

 

 

Dibujar  "a mano alzada"

Propósito

Como vimos ya en el ejemplo un simple programa de dibujo "a mano alzada", tenemos dos posibles aproximaciones para resolver este problema:

  1. Que la clase que describe el canvas, MiCanvas, implemente los interfaces MouseListener y MouseMotionListener, y defina todas las funciones declaradas en dichos interfaces aunque solamente estemos interesados en alguna de ellas.
  1. Crear dos clases anónimas y relacionar el objeto canvas (la fuente de los sucesos asociados al ratón) con objetos de dos clases anónimas que deriven de MouseAdapter y de MouseMotionAdapter.

 

Diseño

El mismo del ejemplo anterior

Respuesta a las acciones del usuario

Se sugiere al lector que trate de resolver por sí mismo este ejercicio, tomando como base el estudio de los sucesos asociados al ratón

1.-La clase que describe el canvas implementa los interfaces MouseListener y MouseMotionListener

disco.gif (1035 bytes)canvas4: CanvasApplet4.java, MiCanvas.java

En el constructor de la clase MiCanvas asociamos mediante addMouseListener y addMouseMotionListener, el productor de los sucesos asociados al ratón, el canvas (this) con el objeto (this) de la clase que implementa los interfaces MouseListener y MouseMotionListener, y que maneja dichos sucesos definiendo las funciones declaradas en dichos interfaces.

El código de la clase MiCanvas, sería el siguiente

package canvas4;

import java.awt.*;
import java.awt.event.*;
public class MiCanvas extends Canvas implements 
			MouseListener, MouseMotionListener{
    int uX, uY;
    public MiCanvas() {
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }
 //interface MouseListener
    public void mousePressed(MouseEvent ev) {
        uX=ev.getX();
        uY=ev.getY();
    }

    public void mouseExited(MouseEvent event) {}
    public void mouseReleased(MouseEvent event) {}
    public void mouseClicked(MouseEvent event) {}
    public void mouseEntered(MouseEvent event) {}
 //interface MouseMotionListener
    public void mouseDragged(MouseEvent ev) {
        int x = ev.getX();
        int y = ev.getY();
        Graphics g=getGraphics();
        g.drawLine(uX, uY, x, y);
        uX=x;   uY=y;
        g.dispose();
    }
    public void mouseMoved(MouseEvent event) {}
}

 

2.-Creamos dos clases anónimas que derivan respectivamente de MouseAdapter y de MouseMotionAdapter

disco.gif (1035 bytes)canvas5: CanvasApplet5.java, MiCanvas.java

Definimos la clase MiCanvas derivada de Canvas, creamos un objeto canvas de dicha clase y lo situamos en el centro del applet. En modo diseño, seleccionamos el objeto canvas en el panel de componentes y en el panel Events situado a la derecha hacemos doble-clic sobre el editor asociado a mousePressed y mouseDragged. JBuilder genera el código tal como se ha explicado en las páginas anteriores.

Como vemos en el listado, se asocia el control canvas, donde se van a producir los sucesos relacionados con el ratón, con dos objetos de dos clases anóminas que derivan, respectivamente de las clases MouseAdapter y MouseMotionAdapter, y que redefine las funciones mousePressed y mouseDragged.

public class CanvasApplet5 extends Applet {
    MiCanvas canvas;
    BorderLayout borderLayout1 = new BorderLayout();

    public void init() {
        canvas=new MiCanvas();
        this.setLayout(borderLayout1);
        this.add(canvas, BorderLayout.CENTER);
        canvas.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                canvas_mousePressed(e);
            }
        });
        canvas.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(MouseEvent e) {
                canvas_mouseDragged(e);
            }
        });
     }

    void canvas_mouseDragged(MouseEvent e) {
        canvas.dibujaCurva(e.getX(), e.getY());
    }

    void canvas_mousePressed(MouseEvent e) {
         canvas.puntoInicial(e.getX(), e.getY());
    }
}

Desde la función respuesta canvas_mousePressed se llama a la función miembro puntoInicial de la clase que describe el canvas, MiCanvas, y le pasa las coordendas del punto del canvas donde se ha pulsado el botón iquierdo del ratón.

Desde la función respuesta canvas_mouseDragged se llama a la función miembro dibujaCurva de la clase que describe el canvas, MiCanvas, y le pasa las coordendas del punto del canvas donde está situado el puntero del ratón a medida que se va arrastrando.

La definición de la clase MiCanvas, es la siguiente

package canvas5;

import java.awt.*;
public class MiCanvas extends Canvas{
    int uX, uY;
    public MiCanvas() {
    }
    public void puntoInicial(int x, int y) {
        uX=x;
        uY=y;
    }

    public void dibujaCurva(int x, int y) {
        Graphics g=getGraphics();
        g.drawLine(uX, uY, x, y);
        uX=x;   uY=y;
        g.dispose();
    }  
}