F # - Eventos
Los eventos permiten que las clases se envíen y reciban mensajes entre sí.
En la GUI, los eventos son acciones del usuario como presionar teclas, clics, movimientos del mouse, etc., o alguna ocurrencia como notificaciones generadas por el sistema. Las aplicaciones deben responder a los eventos cuando ocurren. Por ejemplo, interrumpe. Los eventos se utilizan para la comunicación entre procesos.
Los objetos se comunican entre sí a través del paso de mensajes sincrónico.
Los eventos se adjuntan a otras funciones; registro de objetoscallback funciones a un evento, y estas devoluciones de llamada se ejecutan cuando (y si) el evento es activado por algún objeto.
El módulo de eventos y clases de eventos
La clase Control.Event <'T> ayuda a crear un objeto o evento observable.
Tiene los siguientes miembros de instancia para trabajar con los eventos:
Miembro | Descripción |
---|---|
Publicar | Publica una observación como valor de primera clase. |
Desencadenar | Activa una observación utilizando los parámetros dados. |
El módulo Control.Event proporciona funciones para gestionar flujos de eventos:
Valor | Descripción |
---|---|
agregar: ('T → unidad) → Evento <' Del, 'T> → unidad | Ejecuta la función dada cada vez que se activa el evento dado. |
elija: ('T →' opción U) → IEvent <'Del,' T> → IEvent <'U> | Devuelve un nuevo evento que se activa en una selección de mensajes del evento original. La función de selección lleva un mensaje original a un mensaje nuevo opcional. |
filtro: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> | Devuelve un nuevo evento que escucha el evento original y desencadena el evento resultante solo cuando el argumento del evento pasa la función dada. |
mapa: ('T →' U) → IEvent <'Del,' T> → IEvent <'U> | Devuelve un nuevo evento que pasa valores transformados por la función dada. |
fusionar: IEvent <'Del1,' T> → IEvent <'Del2,' T> → IEvent <'T> | Activa el evento de salida cuando se activa cualquiera de los eventos de entrada. |
por pares: IEvent <'Del,' T> → IEvent <'T *' T> | Devuelve un nuevo evento que se activa en el segundo y subsiguientes disparos del evento de entrada. losNth La activación del evento de entrada pasa los argumentos del N-1th y Nthdisparando como un par. El argumento pasó alN-1th El disparo se mantiene en estado interno oculto hasta que Nth ocurre la activación. |
partición: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> * IEvent <'T> | Devuelve un nuevo evento que escucha el evento original y activa el primer evento resultante si la aplicación del predicado a los argumentos del evento devolvió verdadero y el segundo evento si devolvió falso. |
escanear: ('U →' T → 'U) →' U → IEvent <'Del,' T> → IEvent <'U> | Devuelve un nuevo evento que consiste en los resultados de aplicar la función de acumulación dada a valores sucesivos activados en el evento de entrada. Un elemento de estado interno registra el valor actual del parámetro de estado. El estado interno no se bloquea durante la ejecución de la función de acumulación, por lo que se debe tener cuidado de que la entrada IEvent no se active por varios subprocesos simultáneamente. |
split: ('T → Opción <' U1, 'U2>) → IEvent <' Del, 'T> → IEvent <' U1> * IEvent <'U2> | Devuelve un nuevo evento que escucha el evento original y desencadena el primer evento resultante si la aplicación de la función a los argumentos del evento devolvió Choice1Of2 y el segundo evento si devuelve Choice2Of2. |
Creando eventos
Los eventos se crean y utilizan a través del Eventclase. El constructor de eventos se utiliza para crear un evento.
Ejemplo
type Worker(name : string, shift : string) =
let mutable _name = name;
let mutable _shift = shift;
let nameChanged = new Event<unit>() (* creates event *)
let shiftChanged = new Event<unit>() (* creates event *)
member this.Name
with get() = _name
and set(value) = _name <- value
member this.Shift
with get() = _shift
and set(value) = _shift <- value
Después de esto, debe exponer el campo nameChanged como un miembro público, para que los oyentes puedan conectarse al evento para el que usa el Publish propiedad del evento -
type Worker(name : string, shift : string) =
let mutable _name = name;
let mutable _shift = shift;
let nameChanged = new Event<unit>() (* creates event *)
let shiftChanged = new Event<unit>() (* creates event *)
member this.NameChanged = nameChanged.Publish (* exposed event handler *)
member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)
member this.Name
with get() = _name
and set(value) = _name <- value
nameChanged.Trigger() (* invokes event handler *)
member this.Shift
with get() = _shift
and set(value) = _shift <- value
shiftChanged.Trigger() (* invokes event handler *)
A continuación, agrega devoluciones de llamada a los controladores de eventos. Cada controlador de eventos tiene el tipo IEvent <'T>, que proporciona varios métodos:
Método | Descripción |
---|---|
val Agregar: evento :( 'T → unidad) → unidad | Conecta una función de escucha al evento. Se invocará al oyente cuando se active el evento. |
val AddHandler: 'del → unidad | Conecta un objeto delegado de controlador al evento. Un controlador se puede eliminar posteriormente mediante RemoveHandler. Se invocará al oyente cuando se active el evento. |
val RemoveHandler: 'del → unidad | Elimina un delegado de escucha de un almacén de escucha de eventos. |
La siguiente sección proporciona un ejemplo completo.
Ejemplo
El siguiente ejemplo demuestra el concepto y las técnicas discutidas anteriormente:
type Worker(name : string, shift : string) =
let mutable _name = name;
let mutable _shift = shift;
let nameChanged = new Event<unit>() (* creates event *)
let shiftChanged = new Event<unit>() (* creates event *)
member this.NameChanged = nameChanged.Publish (* exposed event handler *)
member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)
member this.Name
with get() = _name
and set(value) =
_name <- value
nameChanged.Trigger() (* invokes event handler *)
member this.Shift
with get() = _shift
and set(value) =
_shift <- value
shiftChanged.Trigger() (* invokes event handler *)
let wk = new Worker("Wilson", "Evening")
wk.NameChanged.Add(fun () -> printfn "Worker changed name! New name: %s" wk.Name)
wk.Name <- "William"
wk.NameChanged.Add(fun () -> printfn "-- Another handler attached to NameChanged!")
wk.Name <- "Bill"
wk.ShiftChanged.Add(fun () -> printfn "Worker changed shift! New shift: %s" wk.Shift)
wk.Shift <- "Morning"
wk.ShiftChanged.Add(fun () -> printfn "-- Another handler attached to ShiftChanged!")
wk.Shift <- "Night"
Cuando compila y ejecuta el programa, produce el siguiente resultado:
Worker changed name! New name: William
Worker changed name! New name: Bill
-- Another handler attached to NameChanged!
Worker changed shift! New shift: Morning
Worker changed shift! New shift: Night
-- Another handler attached to ShiftChanged!