イベントハンドラ
マウスでクリックしたり、キーボードで入力した時、データベースから通知が来た時などの「イベント」が生じた時にそれを処理するためのプログラムの部分を「イベントハンドラ」という。
Apolloではイベントは原則として「on_」(または「before_」「after_」)から始まるメソッドとして定義されている。したがって、どんなイベントがあるのかは次のようなメソッドで調べることができる。(Phi::Form で調べると 72 個も出てくる、その半分なので36種類のイベントがある)
#! ruby -Ks require "phi" puts Phi::Form.instance_methods.grep(/^on_/).sort
Apolloのイベントハンドラを作成するには2種類の方法がある。
次の例示は、いずれも、フォームをクリックすると、フォームのキャプションに適当な文字列を表示し、同時に、標準出力に引数の内容を表示する。
(a)メソッドタイプ(非推奨)
#! ruby -Ks require "phi" class MyForm < Phi::Form def on_click(*args) p [:form_clicked,args] self.caption = "メソッド型のハンドラ!" end end form = MyForm.new form.show Phi.mainloop
(b)オブジェクトタイプ(推奨)
(b−1)procオブジェクトを直接代入する方法
#! ruby -Ks require "phi" class MyForm < Phi::Form def initialize self.on_click = proc{|sender,*args| p [:form_clicked,sender,args] sender.caption = "procオブジェクト型のハンドラ(1)!" } end end form = MyForm.new form.show Phi.mainloop
(b−2)procオブジェクトを別に作っておいて代入する方法
複数のイベントに同じハンドラを代入することができる。どのイベントから呼ばれたのかを判断するには sender 引数で判断できる。
#! ruby -Ks require "phi" class MyForm < Phi::Form def initialize on_click_proc = proc{|sender,*args| p [:form_clicked,sender,args] sender.caption = "procオブジェクト型のハンドラ(2)!" } self.on_click = on_click_proc end end form = MyForm.new form.show Phi.mainloop
(b−3) メソッドで作っておいて、procオブジェクトに変換して代入する方法
initialize メソッドから追い出すことができる。
#! ruby -Ks require "phi" class MyForm < Phi::Form def initialize self.on_click = proc{|*args|form_on_click(*args)} end def form_on_click( sender,*args ) p [:form_clicked,sender,args] sender.caption = "メソッド+Procオブジェクト型のハンドラ!" end end form = MyForm.new form.show Phi.mainloop
(b−4)メソッドで作っておいてMethodオブジェクトに変換して代入する方法。
引数はメソッドに従うので、多少短くなる。
#! ruby -Ks require "phi" class MyForm < Phi::Form def initialize self.on_click = method(:form_on_click) end def form_on_click( sender,*args ) p [:form_clicked,sender,args] sender.caption = "メソッド+Methodオブジェクト型のハンドラ!" end end form = MyForm.new form.show Phi.mainloop
イベントハンドラから戻り値を返す必要がある場合の作り方
キーボードイベントのハンドラでは、nil を返した場合にはkeyコードは変化しないが、数値を返した場合には key コードとして扱われる。
エディット窓で[ret]キーを押した時に次のエディット窓に移動するようにするハンドラは次のように書く。
#! ruby -Ks require "phi" form = Phi::Form.new edit1 = Phi::Edit.new form edit2 = Phi::Edit.new form edit2.top = edit1.bottom edit1.on_key_press = proc{|sender,key| if key == Phi::VK_RETURN form.caption = "edit1 [ret]" edit2.set_focus key = 0 end key # key を返す } edit2.on_key_press = proc{|sender,key| if key == Phi::VK_RETURN form.caption = "edit2 [ret]" edit1.set_focus key = 0 end key # key を返す } form.show Phi.mainloop
Keyword(s):
References: