DrawInto: Dibuja tus controles en Xojo Desktop

DrawInto es el método encargado de dibujar el aspecto de un control gráfico (UI) en otro contexto gráfico asignado como argumento. A continuación encontrarás por qué, probablemente, quieras implementar tu propia versión.

Ya sabemos que el lenguaje de programación Xojo es Orientado a Objetos (OOP), y esto significa que todos los tipos de datos, especialmente aquellos que no son primitivos, utilizan o pueden utilizar lo que se denomina una jerarquía de clases.

Descarga el proyecto Xojo de ejemplo

Esto significa que una clase dada, ya sea cualquiera de las disponibles en el Framework de Xojo o bien las creadas por nosotros mismos, pueden actuar como clase padre o raíz a partir de la cual podemos crear otras clases.

La gran ventaja de crear una jerarquía de clases es que todas aquellas clases derivadas compartirán el mismo conjunto de métodos, propiedades y eventos declarados en la clase superior (no marcados con un ámbito Privado) y, por tanto, podemos hacer que nuestro código sea más flexible, fácil de mantener y también conseguir un mayor dinamismo en tiempo de ejecución de nuestras aplicaciones gracias a la proyección o Casting de objetos.

Qué es DrawInto y como funciona

¿A que viene todo esto? Muy sencillo. En el tema que nos ocupa, todos y cada uno de los controles gráficos o de interfaz de usuario (UI) proporcionados por el framework de Xojo derivan de la clase raíz RectControl (la cual deriva a su vez de la clase base Control), y entre otros de los métodos definidos por dicha clase en aplicaciones Desktop encontramos DrawInto.

Esto significa que cada uno de los controles gráficos tiene la capacidad de dibujarse a sí mismo en cualquier otro control o bien cualquier otro contexto gráfico que le indiquemos.

Eso sí, una vez dibujados en el contexto de destino perderán todas sus capacidades de interacción y respuesta a código. Es decir, serán meras representaciones gráficas sobre el contexto gráfico de destino que se utilice, lo cual no deja de ser tremendamente útil e interesante.

Sin ir más lejos, este es el método que se utiliza en AXControlGrid para el renderizado de todos los controles de las páginas seleccionadas para la obtención de los correspondientes objetos Picture equivalentes al contenido de cada página.

Como puedes comprobar en la documentación de Xojo, la signatura de DrawInto es la siguiente:

RectControl.DrawInto(g as Graphics,x as Integer, y as Integer)

  • Lo primero que puedes observar es que el método se invoca sobre la instancia de objeto (control de interfaz de usuario) que queramos dibujar sobre un contexto gráfico determinado.
  • En segundo lugar, el primero de los argumentos pasados en el método DrawInto se corresponde con el contexto gráfico sobre el cual deseamos dibujar nuestro control. Ten en cuenta que podemos obtener dicho contexto gráfico a partir de múltiples objetos, como por ejemplo Picture.
  • En tercer lugar, los argumentos x e y se corresponden con las coordenadas correspondientes al vértice superior izquierdo sobre el que deseemos plasmar el dibujado del control en el contexto gráfico de destino.

En la mayoría de los casos y usos, puedes invocar este método tal cual para obtener los resultados deseados. Esto es, la instancia del control que invoque el método se dibujará tal y como se indique en su evento Paint sobre el contexto gráfico de destino.

Ahora bien, en muchas otras ocasiones quizá no quieras obtener sobre el contexto gráfico de destino la misma representación gráfica que se ve en la pantalla: omitir por ejemplo el dibujado de las líneas de contorno, modificar determinados colores o bien valores mostrados en pantalla, o bien modificar los cálculos de coordenadas realizadas en el evento Paint de la instancia que invoca el método y que estarían fuera de rango cuando se aplican sobre el contexto gráfico de destino.

Después de todo ten en cuenta algo fundamental para entender como funciona DrawInto:

  • Cuando la instancia de un objeto invoca este método, lo que ocurrirá en realidad es que el código presente en el evento Paint se ejecutará sobre el nuevo contexto gráfico pasado como argumento.
  • Por supuesto, si no has implementado el evento Paint en tu propia clase lo que ocurrirá es que se ejecutará la implementación por omisión, tal y como ocurre en cualquier otro evento disponible para la clase y que no se haya sobreescrito (es decir, personalizado su función o comportamiento).

DrawInto: App de ejemplo en funcionamiento

Modificar el comportamiento estándar de DrawInto

Por otra parte, y especialmente en Windows, es posible que en determinados casos no obtengas un dibujado correcto sobre el nuevo contexto gráfico cuando se hace la llamada a DrawInto estándar (la implementada por omisión).

Si te hallas en la misma situación, además de los casos expuestos anteriormente, entonces el modo que tienes a tu alcance es la sobreescritura del método DrawInto en tus propias clases gráficas.

Al hacerlo, cada vez que se ejecute dicho método se ejecutará el código que hayas incorporado en él, y eso significa que tendrás control tanto del contexto gráfico recibido como parámetro (tamaño y coordenadas en las que se espera que dibujes el control), así como de las operaciones de dibujado propiamente dichas a partir de todos los métodos disponibles a través de la clase Graphics.

La forma de implementar (sobreescribir) el método DrawInto en tus propios controles gráficos (todos aquellos derivados de RectControl) es tan sencillo como probablemente ya lo hayas experimentado en el caso de añadir Eventos u otros Métodos a tus propias subclases.

Una vez tengas tu clase seleccionada en el Navegador de Proyectos del IDE de Xojo, sólo has de utilizar el menú contextual para seleccionar la opción Add to "instanceName" > Method y elegir la opción DrawInto(graphics as Graphics, Left as Integer, Top as Integer).

Cuando lo hagas, verás que el Editor de Código asociado implementa por omisión una llamada al mismo método de la clase Superior (aquella de la que deriva tu control).

Esto permite que se realice el dibujado requerido por la jerarquía de clase en la que se base tu control.

A efectos prácticos, puedes prescindir de la llamada a dicho método en la clase superior (recorriendo toda la jerarquía hacia arriba) en aquellos casos en los que quieras tomar el control absoluto de lo que deseas dibujar sobre el contexto gráfico recibido.

Este enfoque tendrá también la ventaja adicional de que ahorrarás tiempos de dibujado, puesto que evitarás múltiples llamadas de dibujado.

Por último, todo lo que tendrás que hacer será añadir en dicho método sobreescrito el código encargado de dibujar lo que desees sobre el contexto gráfico… ¡y listo! A partir de ese momento, cuando realices una llamada sobre:

aRectControlInstance.DrawInto( tContext, 100, 100 )

Se ejecutará el código incluido en tu propia implementación del método DrawInto, obteniendo así una mayor flexibilidad y control sobre lo que se dibuje.

Eso sí, como de costumbre, no olvides comprobar los resultados especialmente en Windows en función de que tu control deba de soportar múltiples versiones del IDE de Xojo; puesto que a lo largo de varias ediciones se ha ido modificando de forma sustancial todo lo relacionado con el aspecto gráfico.

DrawInto en práctica

Para ver el funcionamiento de lo expuesto sobre DrawInto, vamos a realizar un ejemplo sencillo en Xojo. Para ello crea un nuevo proyecto de tipo Desktop y añade una clase basada en Canvas sobre el Navegador de Proyecto.

A continuación y con la nueva canvas seleccionada, accede al Panel Inspector para asignar los siguientes valores:

  • Name: MyOwnControl
  • Super: Canvas

Con nuestra clase aun seleccionada, añade el evento Paint accediendo al menú contextual y seleccionando la opción Add to "MyOwnControl" > Event Handler…" y seleccionando Paint en la ventana resultante.

En el Editor de Código correspondiente al manejador de evento Paint, introduce el siguiente código:

g.ForeColor = &cff0000
g.FillRect(0,0,g.Width, g.Height)

Nada especialmente significativo. Como puedes ver, se limita a definir el color rojo como color de primer plano y a continuación rellena un rectángulo correspondiente a todo el área del control con el color definido.

Ahora es el momento de sobreescribir el método DrawInto. Con nuestra clase aun seleccionada, añade el método DrawInto e introduce el siguiente código en el Editor de Código correspondiente:

// Uncomment the following line of code to see what happens!
// In that Case, the control first executes the code from the Paint Event,
// executing the drawing code from the overriden DrawInto method afterwards.

//super.DrawInto(graphics, left, top)

Dim s As String = "From DrawInto"

Dim sLen As Double = graphics.StringWidth( s ) / 2

graphics.ForeColor = &c00FF00

// No matter what are the "Left" and "Top" values, we don't use them
// for our custom drawing.

graphics.DrawRect(0,0, graphics.Width, graphics.Height)

graphics.ForeColor = &c000000
graphics.PenHeight = 1
graphics.PenWidth = 1
graphics.AntiAlias = True

graphics.DrawString("From DrawInto", (graphics.Width/2) - sLen, (graphics.Height / 2) )

Básicamente, lo que hacemos aquí con DrawInto es cambiar sustancialmente la representación del control entre lo que se ve cuando se dibuja en la pantalla mediante el evento Paint, y lo que se obtiene cuando se invoca el método DrawInto sobre la instancia. En este segundo caso pasará a dibujar el contorno del control con el color verde y dibujará centrado el texto en la mitad del control.

Puedes observar que la línea: Super.DrawInto(graphics, Left, Top) está comentada. Luego puedes hacer pruebas para comprobar qué es lo que ocurre en el programa de ejemplo si quitas el comentario de dicha línea o bien si lo dejas puesto. ¡La diferencia es notable!

Dando forma a la aplicación de ejemplo

Con nuestra clase definida es el momento de comenzar a crear la interfaz de usuario para nuestra pequeña aplicación de ejemplo sobre DrawInto. Algo realmente sencillo.

Selecciona la ventana Window1 para acceder al Editor de Diseño y arrastra a continuación el elemento MyOwnControl desde el Navegador de Proyecto sobre el editor. Con ello habremos añadido una nueva instancia a partir de nuestra clase cuyo nombre será MyOwnControl1.

A continuación, arrastra un Canvas estándar desde el panel de Librería también sobre la ventana. Pasará a crearse una nueva instancia con el nombre Canvas1.

Por último, añade un botón también desde la librería sobre la ventana de nuestra aplicación y utiliza el Panel Inspector para que su nombre sea pbDrawInto. Este será el botón encargado de indicar a nuestra instancia MyOwnControl1 que se dibuje en el contexto gráfico proporcionado por Canvas1.

Para ello, con el botón pbDrawInto seleccionado, añade el Manejador de Evento Action e incluye el siguiente código en el Editor de Código asociado:

// We create a Picture we can use to give a Graphics context to the
// Canvas1 backdrop (it would be "Nil" by default)

Dim p As New Picture( canvas1.Width, Canvas1.Height, 32 )

canvas1.Backdrop = p

// And we instruct our "MyOwnControl" instance to draw itself on the
// "Canvas1" graphics context.

MyOwnControl1.DrawInto(Canvas1.Backdrop.Graphics,0,0)

Procura que el aspecto final de la interfaz de usuario sea similar a la mostrada en la siguiente imagen, si bien puedes optar por cualquier otra.

DrawInto: app de ejemplo en el IDE
Con esto, ya tenemos nuestra aplicación de ejemplo lista para funcionar. Pulsa el botón Run en el IDE y comprueba los resultados entre lo que se muestra con el evento Paint y lo que se obtiene al pulsar el botón etiquetado DrawInto.

Deja un comentario

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