Escribe tu búsqueda

Eventos en Xojo, Métodos que se “disparan”

Compartir

En la última entrega nos llegamos hasta los destructores de clase, la forma elegante de limpiar nuestros objetos de clase mediante un método que equilibra la función del constructor. En esta ocasión veremos otro tipo de métodos muy especiales: los Eventos.

¿Recuerdas cuando en uno de los primeros capítulos te dije que Xojo era un lenguaje de programación orientado a objetos? Pues bien, no solo es así, sino {++que además también es un lenguaje de programación orientado a Eventos++} . ¿Qué significa esto? Pues que el código incluido en dicho tipo de métodos se ejecutará como respuesta a las acciones realizadas por el usuario sobre los elementos de la interfaz de usuario, por lo general, o bien cuando sea nuestra propia aplicación la responsable de disparar dichos eventos.

De hecho, la programación dirigida a eventos es igualmente compleja si tenemos en cuenta que se realiza de forma asíncrona y que, bastantes ocasiones, la acción producida por el código de un evento puede disparar nuevos evento ¡entre ellos el evento original! Esto da lugar en más casos de los que podamos imaginar a bugs de lo más particulares o bien problemas de rendimiento (¿qué tal redibujar más de 10 veces un mismo control o actualizar tres veces consecutivas las entradas de un listado, por ejemplo?). Por tanto, a la hora de incluir código en este tipo de métodos conviene ser cautos sobre el tipo de acciones que puede desencadenar.

Porque si bien los Controles de UI incluidos en el Framework de Xojo son en principio los primeros proveedores de Eventos (así como las clases derivadas de los mismos o subclases), nada impide que definamos nuestros propios eventos de clase y dispararlos cuando sea preciso. (Ten en cuenta que el uso del término disparar un evento está realmente generalizado, y se corresponde con la respuesta que ocurre ante una acción.)

Eventos en Controles

La forma más sencilla de comenzar a trabajar con los eventos no es otra que utilizando cualquiera de los disponibles. Si has estado atento, en los capítulos anteriores hemos utilizado bastante un evento: Open. Este es el que se dispara cada vez que un elemento gráfico cobra vida (está a punto de ser visible para el usuario). Por tanto, aquí es donde se suele incluir en todos los casos gran parte del código de “preparación”, tales como creación de nuevas instancias que deban de añadirse a las propiedades del control, inicialización de variables, etc.

Ahora bien, para ver y añadir los eventos soportados por un tipo de objeto en concreto, selecciona dicho objeto en primer lugar en el Área de Navegación (Por ejemplo el objeto Window1) y, a continuación, utiliza el atajo de teclado Comando + Opción + E para abrir la hoja donde aparecerán listados.

Algo que agradecerás especialmente si estos son tus primeros pasos con Xojo es que solo tendrás que seleccionar cada uno de los eventos mostrados en el listado para obtener una descripción de lo que hacen y bajo qué situaciones se disparan. Por ejemplo, en la captura puedes ver que está seleccionado el evento Paint donde se ofrece como atributo la variable ‘g’ de tipo Graphics y que se dispara siempre que se hace necesario redibujar los contenidos de la ventana. Selecciónalo y pulsa el botón ‘Ok’.

Verás que bajo la entrada correspondiente a Window1 se ha añadido Event Handlers, de la que ahora cuelga el evento recién añadido: Paint. Selecciónalo e introduce el siguiente código en el Editor de Código:

      dim r as new Random
      g.ForeColor = RGB(r.InRange(0,255), r.InRange(0,255), r.InRange(0,255))
      g.FillRect(0,0,me.Width,me.Height)

Ejecuta el programa y modifica el tamaño de la ventana tantas veces como quieras (¡cuidado con tus ojos!). Como habrás comprobado, el color de fondo de la ventana cambia de forma aleatoria cada vez que necesita volver a actualizarse o pintarse.

La Cadena De Eventos

Hasta aquí, la parte sencilla. Como has visto, para utilizar un evento sólo tienes que añadirlo al elemento, incluir el código que se ejecutará cuando tenga lugar, y listo. Ahora bien, muchos controles comparten comportamientos que se producen cuando ocurre el mismo tipo de evento. Por ejemplo, la clase ventana, al igual que otros muchos controles de Xojo soportan el evento KeyDown que tiene lugar cada vez que el usuario pulsa una tecla. En estos casos, ¿quién se encarga de responder al evento?

Añade por ejemplo el evento KeyDown en el elemento Window1 (ya sabes como hacerlo), e introduce la siguiente línea de código para dicho evento:

    Beep

Ahora añade un nuevo control sobre la ventana de tipo TextArea y ajústalo para que ocupe el área máxima disponible dentro de la ventana. Para que el control se ajuste a medida que se modifica el tamaño de la ventana, asegúrate de anclar el control utilizando el apartado Locking del Inspector, tal y como se muestra en la siguiente imagen:

Antes de seguir, asegúrate de eliminar el código que escribimos anteriormente en el evento Paint, sería un constante mareo seguir con ello. Ejecuta la aplicación.

¿Qué ocurre? Pues que el control TextArea realiza su función y consume todos los eventos correspondientes al teclado, de modo que éstos no llegan a propagarse hacia los elementos inferiores: la ventana sobre la que se asienta dicho control. Después de todo, un control TextArea está concebido para que escribamos texto, ¿verdad? Elimina el control TextArea y vuelve a ejecutar la aplicación. Comprobarás que ahora sonará un “beep” cada vez que pulses una tecla, lo que significa que el evento está llegando al manejados que hemos incorporado a la ventana para su tratamiento.

Ahora bien, mediante los manejadores de eventos podemos modificar el comportamiento original de un control. Por ejemplo, creemos una versión del control TextArea en el que sólo se pueda escribir texto, símbolos y otros caracteres, pero no números.

Vuelve a añadir un control TextArea sobre la ventana tal y como hiciste anteriormente, y en esta ocasión añade un manejados de evento KeyDown escribiendo el siguiente código en el Editor de Código correspondiente:

    if key.asc >47 and key.asc < 58 then Return true

Ejecuta la aplicación y prueba a escribir tanto letras como números. Verás que en el primer caso el control se comporta como esperas, mientras que en el segundo… simplemente no quedan reflejados los números tecleados.

¿Y por qué hay que devolver true como respuesta del método? Bien visto. Como puedes observar, muchos de los gestores de eventos incluyen en su signatura la devolución de un valor booleano. Cuando devolvemos un valor de true estamos indicando a la clase que nos hemos encargado de gestionar el evento, de modo que alteramos el comportamiento original establecido por la clase. Prueba a devolver el valor false, ¿qué ocurre? Efectivamente, no funcionará como esperamos; dado que en aquellos casos en los que se cumple la condición estaremos dejando en manos del gestor de eventos original de la clase su procesamiento.

Definiendo Nuestros Propios Eventos

En el anterior ejemplo de TextArea hemos visto como podemos obtener una versión especializada de un control ya incluido por el framework de Xojo. Sin embargo, dejarlo tal cual para su uso en otras aplicaciones o incluso por parte de otros desarrolladores no resultaría muy elegante, dado que éstos se encontrarían ya con nuestro código en el gestor del evento y, si precisan incluir código propio en ese mismo evento, podría darse lugar a errores. O bien podrían borrar nuestro código, eliminando su comportamiento especializado por completo.

Como hemos visto capítulos atrás, ¿qué debemos hacer cuando precisamos crear un comportamiento especializado de una clase ya existente? Efectivamente, crear una subclase.

Añade por tanto una nueva clase (Insert > Class) y utiliza el panel Inspector para asignar el nombre de clase e introducir ‘TextArea’ en el campo Super (es decir, la clase a partir de la cual se deriva).

Selecciona la nueva clase en el Navegador de Proyecto y añade el evento KeyDown copiando (o volviendo a escribir) el mismo código que ya utilizamos anteriormente para impedir la introducción de números.

A continuación selecciona el control TextArea que aun está sobre la ventana y utiliza el panel Inspector para cambiar su Super de TextArea a la clase recién creada (en el ejemplo, con el nombre ‘TextAreaWithoutNumers’). Ejecuta la aplicación.

Si todo ha ido “bien” se habrá producido un error del Compilador donde se indica que el control TextArea1 utilizado en Window1 implementa un evento ya definido en su superclase. ¿Qué significa esto? De forma simple: dado que nuestra subclase ya ha añadido dicho evento y, por tanto, lo ha consumido, dicho evento no está disponible para los controles que implemente dicha clase.  Borra el evento ‘KeyDown’ del control TextArea1, ejecuta la aplicación y comprobarás que ahora sí funciona, y con el comportamiento que esperamos.

¿Cómo solucionar el problema? Xojo nos lo pone fácil: definiendo nuestros propios eventos en la clase.

Selecciona de nuevo la clase recién creada en el Navegador de Proyecto  (TextAreaWithoutNumers en nuestro ejemplo) y elige a continuación Insert > Event Definition.

En el panel de Inspector utiliza la misma signatura de KeyDown, tal y como se muestra en la imagen. Por último, selecciona el evento KeyDown original de la subclase y asegúrate de que el código quede como se muestra a continuación:

      if key.asc >47 and key.asc < 58 then Return true
      return RaiseEvent KeyDown(key)

Como ves, se ha añadido la instrucción ‘RaiseEvent KeyDown(key)’. La instrucción RaiseEvent es la encargada de llamar al evento cuya definición hayamos incluido en la clase. De hecho, no se puede utilizar la instrucción RaiseEvent fuera de la clase o desde una instancia de la clase para lograr el mismo propósito.

Por tanto, nuestra clase se encarga de gestionar en primer lugar el procesado de la pulsación de teclas añadiendo el comportamiento especializado de impedir la introducción de números y, si la tecla pulsada no se corresponde con un número, se encarga de llamar nuevamente al evento definido, pasando la tecla como parámetro, para que pueda ser procesada por cualquier instancia de la clase.

Para ponerlo en práctica, y como conclusión, vuelve a seleccionar el control TextArea1 y añade nuevamente el manejados de evento KeyDown. En esta ocasión añadiremos como comportamiento que impida la introducción de las letras ‘a’ y ‘z’, y que se sumará a la no escritura de números, definido por la clase. Utiliza para ello el siguiente código en el gestor del evento:

Ejecuta la aplicación y comprueba su funcionamiento.

Ampliar clases ya existentes

Si bien hay mucho más detrás de los Eventos, ahora ya tendrás algo más claro qué son, cuál es su función y en qué casos se utilizan o puedes definir tus propios eventos.

En la siguiente entrega veremos otra de las capacidades de las que puedes sacar mucho jugo, y ahorrarte una buena cantidad de trabajo, no por comodidad sino por tratarse en muchos casos de una opción preferible frente a la creación de subclases: los métodos de extensión de clase.

 

Enlaces de Interés sobre Xojo

Artículos anteriores

Javier Rodríguez (@bloguintosh) es desarrollador OS X e iOS, director de Macsoluciones.com. Puedes contactar con él para el desarrollo de aplicaciones para Mac e iOS en entornos empresariales así como consultoría y formación.

Dejar un comentario

Twitter
Visit Us
Tweet
YouTube
Pinterest
LinkedIn
Share