イベント
UIngアプリケーションは、コールバックブロックを使ってネイティブイベントに応答します。
コールバックはインターフェースの構築中、UIng.mainを呼ぶ前に登録します。次は
最初のアプリケーションで作成したwindowを使う抜粋です。
entry = UIng::Entry.new
button = UIng::Button.new("Greet")
status = UIng::Label.new("Enter your name")
button.on_clicked do
name = entry.text || ""
window.msg_box("Greeting", "Hello, #{name}!")
end
entry.on_changed do |text|
status.text = "#{text.size} characters"
end
必要な場合、コールバックは値を受け取ります。たとえばEntry#on_changedは現在の
テキストを、Slider#on_changedは現在の整数値を渡します。
コールバックの解除
各on_*登録には対応するclear_on_*があります。たとえば
button.clear_on_clickedはbutton.on_clicked(nil)と同じで、
entry.clear_on_changedはentry.on_changed(nil)と同じです。解除すると
Crystalのクロージャへの参照を解放し、コントロールは後で再登録できます。
MenuItem、ToolbarItem、Table、Window、UIng.clear_on_should_quitも同じ規則です。
Area::Handlerではclear_drawやclear_mouse_eventなどを使い、対応する
登録メソッドへnilを渡す場合と同じです。
MultilineEntry#clear_on_changedと#clear_on_changed_with_textは同じ変更通知の
登録枠を解除します。任意の編集コールバックには
Table::Model::Handler#clear_set_cell_valueも使え、set_cell_value(nil)と同じです。
UIng.clear_on_errorはUIng.on_error(nil)と同じです。
libui-ngがNULLでない関数ポインタを必要とする箇所には、解除後も何もしない
ネイティブコールバックを残します。window.clear_on_closingの後は、新規Windowで
終了ハンドラを登録していない場合と同様に、閉じる要求を拒否します。
UIng.clear_on_should_quitの後もアプリケーション全体の終了要求を拒否します。
どちらかの要求に応答させる場合は、改めてハンドラを登録してください。
インターフェースを更新する
ネイティブコントロールの読み書きはUIスレッドで行います。別の場所で実行した処理から
インターフェースを更新する場合は、UIの更新部分だけをUIng.queue_mainで予約します。
UIng.queue_main do
status.text = "Finished"
end
タイマー
UIng.timerにはTime::Spanまたは整数ミリ秒を渡します。どちらも同じタイマーハンドルを
返します。ブロックはUIスレッドで実行され、
trueで継続、falseで停止します。戻り値のタイマーは別のUIコールバックからも
停止できます。
clock = UIng.timer(250.milliseconds) do
status.text = Time.local.to_s
true
end
button.on_clicked { clock.stop }
停止するとclock.stopped?は直ちにtrueになります。stop後は利用者の
ブロックを呼ばず、libui-ngのネイティブタイマーは次の通知時に解除されます。
UIng.timerはUIng.initの後、UIng.uninitの前に呼びます。Time::Spanで指定した
1ミリ秒未満の間隔は切り上げます。整数で指定する場合は1からInt32::MAXミリ秒までです。
以前の整数ミリ秒版を使っていたコードは、間隔をそのまま使い、ブロックの戻り値を
変更します。UIng.timer(250) { true }で継続し、UIng.timer(250) { false }で停止します。
以前の1と0はコンパイルできません。
クロージャは捕捉したCrystalオブジェクトを保持します。使用中のネイティブ資源は解放しないでください。 コールバック内の例外はC側へ伝播せず、UIngがログに記録します。