ランタイムとライフタイム

English

UIngアプリケーションは、UIng.initからUIng.mainまでの間にコントロールを作成します。 メインループはネイティブイベントを待機し、アプリケーションが登録したコールバックを 呼び出します。

アプリケーションのライフサイクル

  • UIng.initはlibui-ngを初期化します。
  • window.showは構築済みのウィンドウを表示します。
  • UIng.mainはネイティブイベントループを実行します。
  • UIng.quitはイベントループに終了を要求します。
  • UIng.uninitはイベントループ終了後にアプリケーション全体のリソースを解放します。

対応するUIng.uninitを呼び忘れないよう、UIng.mainの後には必ずUIng.uninitを 呼んでください。


UIng.init

# ここでインターフェースを構築して表示します。
UIng.main
UIng.uninit

UIng.initにブロックを渡す書き方もあります。この形式では、イベントループが 終了した後にUIng.uninitが自動的に呼び出されます。


UIng.init do
  # ここでインターフェースを構築して表示します。
  UIng.main
end

単一ウィンドウの終了

通常はコントロールを手動で破棄する必要はありません。on_closingでイベントループを 停止してtrueを返すと、libui-ngがWindowとその子を破棄します。


window.on_closing do
  UIng.quit
  true
end

このコールバック内ではwindow.destroyを呼びません。

コントロールの所有権

一部のコントロールは別のコントロールを内包します。内包する側が親、接続された側が 子です。親を破棄するとすべての子も自動的に破棄されるため、通常は最上位の親だけを 破棄します。


window = UIng::Window.new("App", 400, 300)
box = UIng::Box.new(:vertical)
button = UIng::Button.new("OK")

box.append(button)
window.child = box

window.destroy # boxとbuttonも破棄されます

UIngは子のCrystalラッパーも解放済みとして扱います。親を破棄した後に子を使用する ことはできません。

子を別の場所で再利用する場合は、先に親から切り離します。


button.detach
other_box.append(button)

子を個別に破棄する場合も、先に切り離します。


button.detach
button.destroy

接続中の子にdestroyを呼ぶと例外が発生し、子は破棄されずに残ります。

  • WindowとGroupは子を1つ持ちます。nilまたは新しい子を代入すると、以前の子は 破棄されずに切り離されます。
  • Box、Form、Tab、Gridはdelete(child)を利用できます。Box、Form、 Tabではdelete(index)も利用できます。
  • 親を持たないコントロールは直接破棄できます。

ウィンドウとアプリケーションの終了

UIng.quitはイベントループを停止しますが、ウィンドウを破棄しません。 UIng.uninitはアプリケーション全体のリソースを解放しますが、アプリケーションが 作成したウィンドウを破棄しません。UIng.uninitを呼ぶ前に、すべての最上位 ウィンドウが破棄されていることを確認してください。

Window#on_closingは閉じるボタンを処理します。trueならWindowを閉じ、falseなら 開いたままにします。複数Windowでは、各Windowを閉じるたびに無条件でUIng.quitを 呼ばないでください。

UIng.on_should_quitはQuitメニューなど、アプリケーション全体の終了要求を処理します。 すべての最上位Windowを破棄してからtrueを返します。


UIng.on_should_quit do
  window.destroy unless window.released?
  true
end

複数Windowでは同じ処理をすべての最上位Windowに行います。released?は二重破棄を防ぎます。

その他のリソース

コントロール以外のオブジェクトは、取得方法に応じた規則で解放します。

  • .newで作成したオブジェクトやメソッドから直接返されたオブジェクトは、通常、 使用後に解放する必要があります。
  • .openなどのブロック形式で使うオブジェクトは、ブロック終了時に自動解放されます。
  • コールバックへ渡されたオブジェクトは、通常、そのコールバックが返るまでだけ有効です。 解放はUIngが処理します。

個別のリソースには次の規則があります。

  • Table::Model: model.freeの前に、そのモデルを使用するすべてのTableの破棄を 要求します。ネイティブ側の破棄が保留中の場合、ラッパーは直ちに利用不能になり、 最後のTableの破棄完了後にネイティブモデルが解放されます。
  • Image: 不要になったらfreeを呼びます。ImageView#image=へ渡した後は解放できますが、 TableまたはToolbarが使用している間は保持してください。
  • Toolbar: ウィンドウから切り離してからfreeを呼びます。
  • Draw::Path、Draw::TextLayout、AttributedString: 利用できる場合は.openを使い、 ブロック終了時に解放させます。
  • Table::Selection: ブロック形式とコールバック形式では自動解放されます。 table.selectionの直接の戻り値は使用後に解放します。Table::Selection.new(rows)は CrystalのGCが管理します。
  • Table::Value: cell_valueから返した値はlibui-ngが管理します。set_cell_valueへ 渡された値は、そのコールバックが返るまでだけ有効です。
  • Attribute: set_attributeへ渡した後は、受け取ったAttributedStringが管理します。 列挙中にyieldされたAttributeは、そのブロック内だけで有効です。
  • OpenTypeFeaturesとAttributedStringは列挙中に再帰的に読み取れますが、列挙が 終わるまでは解放や構造変更ができません。
  • 描画コンテキストはdrawコールバック中だけ有効です。

destroyまたはfreeを呼ぶと、対応するラッパーは以後利用できません。