Gestión de eventos de teclado

Normalmente cuando queremos introducir textos en un programa utilizaremos los elementos que nos proporciona Cocoa, por ejemplo las clases NSText y NSTextView. Pero a veces nos puede interesar gestionar por nuestra cuenta que hacer con las pulsaciones del teclado.

Esta es una pequeña receta con lo que yo he aprendido de estas cosas. Si no quieres más explicaciones y sólo te interesan los resultados rápidos:

  1. Crear una vista personalizada
  2. Hacer que la vista sea el gestor por defecto
  3. Sobrescribir métodos

Al final hay un resumen con una información un poco más ampliada sobre cómo funcionan los eventos en Cocoa.

Receta

Crear una vista personalizada

Una vez creado el proyecto con XCode abre el programa Interface Builder y crea una nueva clase a partir de la clase NSView.

Creando una vista personalizada

Busca primero la clase NSView y crea una subclase, bien con el botón derecho del ratón o con la opción de menú Classes | Subclass NSView.

Después crea los ficheros de la clase (añadiendolos al proyecto)
Y finalmente crea una instancia de la clase para añadir al proyecto.

Hacer que la vista sea firstResponder

firstResponder
Conectar la ventana del programa con la instancia de la clase que acabamos de crear. Escoger la salida (outlet) InitialFirstResponder.

Sobrescribir los métodos

Hay que sobreescribir tres métodos: keyDown:, insertText:, acceptsFirstResponder

// Recibe la pulsación de una tecla cuando se aprieta.
// y envia el evento recibido al método interpretKeyEvents
// para gestionar las teclas especiales. 
- (void)keyDown:(NSEvent *)elEvento {
    [self interpretKeyEvents:[NSArray arrayWithObject:elEvento]];
}

    //Recibe la cadena de texto con el carácter entrado 
    - (void)insertText:(id)cadena {
        NSLog(@"### Se ha apretado una tecla, %@", cadena);
    }

//Permite aceptar los eventos como gestor por defecto 
    - (BOOL)acceptsFirstResponder {
        return YES;
    }

El método keyDown: es el encargado de recibir la pulsación de una tecla y decidir que se hace con esta pulsación. Es posible gestionar completamente el teclado desde keyDown: Por ejemplo podríamos haber recogido el carácter pulsado con:

NSString *cadena = [elEvento characters];

Pero no es recomendable, ya que perdemos la gestión de todas la teclas especiales como el tabulador, las teclas de flechas, etc. Por eso es preferible escribir un poquito más de código y enviar el evento de pulsación de teclado a otro método (interpretKeyEvents:) que ya esta definido dentro de la clase NSResponder. Si no es una tecla especial nos devolverá un mensaje insertText con el carácter entrado para poder utilizarlo. Recuerda que para utilizar el método hay que enviar un mensaje a un objeto con los datos a tratar. En este caso es un mensaje al propio objeto (self).

El método insertText: recibe una cadena de caracteres, ya que la pulsación de una tecla puede crear caracteres combinados (p.e. ä). En este ejemplo simplemente cogemos la cadena y la publicamos con un formato mínimo en el log del sistema.

El método acceptsFirstResponder es el que permite que la vista que hemos creado reciba las pulsaciones del teclado en primer lugar. Otra vez es un método heredado de NSResponder y nosotros solamente hemos cambiado su valor por defecto de FALSE a TRUE.

Salida en el log:

[Session started at 2007-12-30 22:57:28 +0100.]
2007-12-3022:57:30.883 Teclas[1536] ### Se ha apretado una tecla,h
2007-12-30 22:57:31.805 Teclas[1536] ### Se ha apretado una tecla, e
2007-12-30 22:57:32.466 Teclas[1536] ### Se ha apretado una tecla, m
2007-12-30 22:57:32.815 Teclas[1536] ### Se ha apretado una tecla, k
2007-12-30 22:57:33.585 Teclas[1536] ### Se ha apretado una tecla, D

Eventos y cadena de respuesta

En un sistema operativo moderno suele haber muchos programas funcionando al mismo tiempo. Cada uno de estos programas puede tener sus ventanas abiertas o simplemente hacer tareas del sistema y que no se ven. Y desde luego ocurren cosas: el usuario aprieta una tecla, mueve el ratón, un programa acaba una tarea, etc. Cada una de estas cosas que pueden suceder es un evento.

Cada vez que sucede un evento algún programa tiene que encargarse de responder a ese evento. En Cocoa hay definida lo que se llama cadena de respuesta (“The Responder Chain”), es decir quien y en que orden debe de gestionar los eventos. En un programa con una única ventana activa, la cadena de respuesta es la siguiente:

Cadena de respuesta

Es decir, primero el elemento activo (un botón, un cuadro de texto, un selector, …). En segundo lugar la vista (si existe) y luego la propia ventana del programa. Si el primer elemento no es capaz de responder al evento lo traspasa al siguiente elemento de la cadena y así sucesivamente.

Otra cosa importante a tener en cuenta es como se selecciona el elemento activo. En la terminología de Apple el first responder. La ventana es quien tiene marcado cual de los elementos y vistas de la ventana es el encargado de responder primero a un evento.

NSResponder

NSRespondersADC.
Dentro de la jerarquía de clases que proporciona Cocoa, la clase NSResponder es la que contiene a los objetos capaces de responder a un evento (y por que le habrán puesto Responder? ). Naturalmente cualquier aplicación es capaz de responder y cualquier ventana también. Pero para hacer nuestro programa nos interesan mucho más las vistas (NSView). Ya que nos permitirán responder al evento y separar el código de la representación de los datos (ventana).
Los objetos de estas clases ya tienen predefinidos las variables de clase y métodos necesarios para gestionar los eventos. Eso esta bien, ya que al aprovechar la herencia no hará falta escribir demasiado código. De esta forma el plan de trabajo es el siguiente:

  1. Crear una vista personalizada
  2. Hacer que la vista sea el gestor por defecto
  3. Sobrescribir métodos

He asumido que sabes como trabajar minimamente con XCode e Interface Builder, en caso contrario mira los tutoriales sobre como crear rápidamente programas con XCode.

Más información en:
ADC, Cocoa Event-Handling Guide, [http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/] Diciembre 2007.

Etiquetas: , , ,

Una respuesta to “Gestión de eventos de teclado”

  1. Dibujando con el ratón « Programación Cocoa Says:

    […] con el ratón En entrada anteriores he intentado entender cómo funcionan los eventos de teclado, como se dibujan elementos y como se maneja el patrón MVC. Ahora juntaré estos elementos para […]

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s


A %d blogueros les gusta esto: