DrawingArea y su evento Draw() – II

Retomando el post anterior, vamos a ver -ahora sí- cómo funciona realmente el evento Draw del DrawingArea y cómo nos va a facilitar las cosas para crear movimiento, gráficos incluso algún juego interactivo.

Anteriormente vimos que la Propiedad Cached debía de establecerse a True para evitar el borrado de nuestros dibujos y que para dibujar debíamos de encerrar nuestras sentencias de dibujo entre dos métodos Draw.Begin(device) y Draw.End(). Pues bien, si ahora  hacemos lo contrario, es decir, establecemos Cached = False y omitimos los métodos Begin y End… bueno alguno habrá comprobado que

eso no funciona a menos que pongamos nuestras funciones de dibujo dentro del manejador de eventos _Draw() del DrawingArea (en adelante, “DA” para abreviar).

Lo vemos con un sencillo ejemplo que dibuja una pelota:

1
2
3
4
5
6
7
Public Sub DrawingArea1_Draw()
 
    Draw.FillColor = Color.Red
    Draw.FillStyle = Fill.Solid
    Draw.Circle(DrawingArea1.Width / 2, DrawingArea1.Height / 2, 50)
 
End

draw1
Obtenemos lo que parece la bandera de Japón (WTF?), pero a pesar de que la propiedad Cached está en False, el dibujo no se borra hagamos lo que hagamos.

La razón es porque el DA se vuelve a redibujar siempre que sea necesario, por ejemplo cuando pasamos otra ventana por encima o redimensionamos el formulario. Si quieres comprobar cuándo se ejecuta el evento _Draw(), simplemente inserta una sentencia Print “lo que sea” dentro del evento y podrás verlo. No olvides comentar o borrar dicha sentencia después.

Hasta aquí hemos dejado claro cómo y cuándo funciona el evento _Draw() pero hay otra forma de dispararlo a voluntad, que es empleando el método .Refresh() del DA. Como el control DA es global a nivel de clase, podemos llamarlo desde cualquier parte del código cuando sea necesario. De manera que, para resumir un poco, todas las rutinas de dibujo las vamos a ejecutar desde dentro del manejador del evento _Draw() y llamaremos al método .Refresh cuando nosotros decidamos, o de una manera periódica como por ejemplo desde un Timer o desde otra función. El código dentro del evento _Draw se encarga sólo de dibujar, mientras que las rutinas que modifican lo que se dibuja se ejecutan desde fuera de dicho evento y modifican variables globales (a nivel de clase, Private).
Vamos a modificar el mismo ejemplo para que la “pelota roja” se mueva o cambie de color, simplemente cambiando los valores de las propiedades por variables y sin tocar estructuralmente el contenido del bloque de código dentro de Public Sub DrawingArea1_Draw().

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
' Gambas class file
 
Private posicionX As Integer
Private posicionY As Integer
Private iColor As Integer
 
Public Sub DrawingArea1_Draw()
 
    Draw.FillColor = iColor
    Draw.FillStyle = Fill.Solid
    Draw.Circle(posicionX, posicionY, 20)
 
End
 
Public Sub btnCambiar_Click()
 
    Randomize
    posicionX = Rnd(0, DrawingArea1.Width)
    posicionY = Rnd(0, DrawingArea1.Height)
    iColor = Rnd(Color.Black, Color.White)
    DrawingArea1.Refresh
 
End

ball
Todas las modificaciones las hacemos desde el manejador de eventos del botón “btnCambiar” que actualiza los valores de las variables y finalmente obligamos al DA a redibujar su contenido mediante .Refresh() que obliga a disparar el evento Draw y el código que contiene, tomando los nuevos valores de las variables. Como ejercicio adicional, podéis probar a hacer lo mismo usando un Timer con un intervalo de 1000 (1000 milisegundos = 1 segundo), en lugar de un botón.

A estas alturas creo que ha quedado claro el funcionamiento del evento Draw del DrawingArea y de cómo estructurar el código para separar la lógica por un lado, y de lo que estamos dibujando, por otro. Pensar en las posibilidades de animar dibujos empleando un Timer para refrescar automáticamente el lienzo donde estamos dibujando. Este será el objetivo de la siguiente entrada, donde veremos como representamos un punto en el sistema de coordenadas del drawing area, cómo mover ese punto y conceptos sobre vectores de posición y velocidad. Hasta entonces, sed buenos 😉

Licencia Creative Commons

Publicado en Programación Etiquetado con: , , ,
3 Comentarios en “DrawingArea y su evento Draw() – II
  1. Shell dice:

    ¿ Como no usaste randomize en Form_Open ?. (Para solo una vez)
    Creo que hace lo mismo, que llamarlo varias veces desde el evento Click.
    Lo mismo es totalmente indiferente.

    • jguardon dice:

      También es posible hacerlo. Al ponerlo en el evento click lo que ocurre es que se renueva la semilla cada vez, pero no tiene mayor importancia para este ejemplo. No puse el evento Form_Open para simplificar el código.

  2. aztk dice:

    Hey! buena explicación. Gracias.
    Estaré esperando los próximos posts.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*