イベント (F#)
更新 : 2011 年 1 月
イベントを使用すると、関数呼び出しをユーザーによる操作に関連付けることができます。イベントは、GUI プログラミングの重要な要素です。 イベントは、アプリケーションまたはオペレーティング システムによってトリガーすることもできます。
イベントの処理
Windows フォームや WPF (Windows Presentation Foundation) などの GUI ライブラリを使用する場合、アプリケーションのコードの大半は、ライブラリによって定義されたイベントに応答して実行されます。 これらの定義済みイベントは、フォームやコントロールなどの GUI クラスのメンバーです。 ボタン クリックなどの既存のイベントにカスタム動作を追加するには、次のコードに示すように、目的の名前付きイベント (たとえば、Form クラスの Click イベント) を参照し、Add メソッドを呼び出します。 F# Interactive からこれを実行する場合は、Run の呼び出しを省略します。
open System.Windows.Forms
let form = new Form(Text="F# Windows Form",
Visible = true,
TopMost = true)
form.Click.Add(fun evArgs -> System.Console.Beep())
Application.Run(form)
Add メソッドの型は、('a -> unit) -> unit です。 したがって、イベント ハンドラー メソッドは、1 つのパラメーター (通常はイベント引数) を受け取り、unit を返します。 前の例は、ラムダ式としてのイベント ハンドラーを示しています。 イベント ハンドラーは、次のコード例に示すように、関数値である場合もあります。 次のコード例は、イベントの種類に固有の情報を提供するイベント ハンドラー パラメーターの使い方も示しています。 MouseMove イベントの場合、システムはポインターの X 位置および Y 位置を含む MouseEventArgs オブジェクトを渡します。
open System.Windows.Forms
let Beep evArgs =
System.Console.Beep( )
let form = new Form(Text = "F# Windows Form",
Visible = true,
TopMost = true)
let MouseMoveEventHandler (evArgs : System.Windows.Forms.MouseEventArgs) =
form.Text <- System.String.Format("{0},{1}", evArgs.X, evArgs.Y)
form.Click.Add(Beep)
form.MouseMove.Add(MouseMoveEventHandler)
Application.Run(form)
カスタム イベントの作成
F# イベントは、F# Event クラスによって表されます。このクラスは、IEvent インターフェイスを実装します。 IEvent は、それ自体が、IObservable<T> および IDelegateEvent という他の 2 つのインターフェイスの機能を結合するインターフェイスです。 したがって、Event は、他の言語のデリゲートに相当する機能と、IObservable からの追加機能を備えていることになります。つまり、F# のイベントでは、イベントのフィルター処理がサポートされるほか、F# のファースト クラスの関数とラムダ式をイベント ハンドラーとして使用できます。 この機能は Event モジュールで提供されます。
他の任意の .NET Framework イベントと同様に動作するイベントをクラスに作成するには、クラスのフィールドとして Event を定義する let バインディングをクラスに追加します。 目的のイベント引数の型を型引数として指定することも、指定せずにコンパイラによって適切な型を推論することもできます。 CLI イベントとしてイベントを公開するイベント メンバーも定義する必要があります。 このメンバーには CLIEvent 属性が必要です。 これはプロパティと同様に宣言され、実装では、単にイベントの Publish プロパティを呼び出します。 クラスのユーザーは、公開されたイベントの Add メソッドを使用してハンドラーを追加できます。 Add メソッドの引数はラムダ式にすることができます。 イベントの Trigger プロパティを使用すると、イベントを発生させて、引数をハンドラー関数に渡すことができます。 これを次のコード例に示します。 この例では、イベントの型引数は組として推論され、ラムダ式の引数を表します。
open System.Collections.Generic
type MyClassWithCLIEvent() =
let event1 = new Event<_>()
[<CLIEvent>]
member this.Event1 = event1.Publish
member this.TestEvent(arg) =
event1.Trigger(this, arg)
let classWithEvent = new MyClassWithCLIEvent()
classWithEvent.Event1.Add(fun (sender, arg) ->
printfn "Event1 occurred! Object data: %s" arg)
classWithEvent.TestEvent("Hello World!")
System.Console.ReadLine() |> ignore
出力は次のとおりです。
Event1 occurred! Object data: Hello World!
Event モジュールで提供される追加の機能を以下に示します。 次のコードは、Event.create の基本的な使用例を示しています。イベントおよびトリガー メソッドを作成し、ラムダ式の形式で 2 つのイベント ハンドラーを追加して、イベントを発生させて両方のラムダ式を実行します。
type MyType() =
let myEvent = new Event<_>()
member this.AddHandlers() =
Event.add (fun string1 -> printfn "%s" string1) myEvent.Publish
Event.add (fun string1 -> printfn "Given a value: %s" string1) myEvent.Publish
member this.Trigger(message) =
myEvent.Trigger(message)
let myMyType = MyType()
myMyType.AddHandlers()
myMyType.Trigger("Event occurred.")
このコードの出力は、次のようになります。
Event occurred.
Given a value: Event occurred.
イベント ストリームの処理
Event.add 関数を使用してイベントのイベント ハンドラーを単純に追加する代わりに、Event モジュールの関数を使用して、高度にカスタマイズした方法でイベントのストリームを処理できます。 これを行うには、一連の関数呼び出しの最初の値として、イベントと共に前方パイプ (|>) を使用します。Event モジュールは、以降の関数呼び出しとして機能します。
特定の条件でのみ呼び出されるハンドラーを持つイベントを設定する方法を次のコード例に示します。
let form = new Form(Text = "F# Windows Form",
Visible = true,
TopMost = true)
form.MouseMove
|> Event.filter ( fun evArgs -> evArgs.X > 100 && evArgs.Y > 100)
|> Event.add ( fun evArgs ->
form.BackColor <- System.Drawing.Color.FromArgb(
evArgs.X, evArgs.Y, evArgs.X ^^^ evArgs.Y) )
Observable モジュールには、観測可能なオブジェクトで有効な関数と類似の関数が含まれています。 観測可能なオブジェクトはイベントに似ていますが、オブジェクト自体がサブスクライブされている場合にのみ、イベントをアクティブにサブスクライブします。
参照
参照
概念
その他の技術情報
Control.Event<'Delegate,'Args> クラス (F#)
履歴の変更
日付 |
履歴 |
理由 |
---|---|---|
2011 年 1 月 |
DelegateEvent ではなく Event の使用を強調しました。 |
情報の拡充 |