BitArts Blog

ロードバイク通勤のRubyプログラマで伊豆ダイバー。の個人的なブログ。

wxRubyでハマったこととかまとめ

速度、コーディングのしやすさともに、wxRubyがかなり気に入りつつある。ただ、早くもいくつかの不具合に当たったり、少しハマったところがあったので、まとめておく。

raiseするとwrong # of arguments(1 for 0) (ArgumentError)

仕様ミスでWx::Window#raiseメソッドとコンフリクトしている(wxRuby 2.0.0現在)。解決策としてはriseの代わりにKernel.raiseを使えば良い。この問題はwxRubyの不具合として認知されており、すでにWx::Window#raiseはdeprecatedとなっていて、Wx::Window#bring_to_frontを使うことが推奨されている。

Wx::ListCtrl#get_selectionsで常に[]が返る

バグっているようなので(wxRuby 2.0.0現在)、暫定的に次のようにメソッドを再実装して解決。

class Wx::ListCtrl
  def get_selections
    selections = []
    item = get_next_item(-1, Wx::LIST_NEXT_ALL, Wx::LIST_STATE_SELECTED)
    while item >= 0
      selections << item
      item = get_next_item(item, Wx::LIST_NEXT_BELOW, Wx::LIST_STATE_SELECTED)
      break if item == 0
    end
    selections
  end
end

参照:http://www.ruby-forum.com/topic/181089
(このコードも不具合があったので上記コードで修正済み)

スレッドが回らない

仕様?

Timerを設定して定期的にThread.passを呼んでやる必要がある。 Wx::Window#initializeで次のようにしておく。

Wx::Timer.every(10) { Thread.pass }

ウインドウに制御を渡す方法

でも上記のようにして動かしたスレッドは遅いので積極的に使いたくはない。しかし時間のかかる処理を普通に行うとウインドウが固まってしまうので、定期的にウインドウに制御を渡す必要がある。そのためにはループ内などで定期的に次のようにする。

Wx::get_app.yield

ノンプリエンプティブマルチタスクなOSではもちろん必須。今どきそんなOSがあるのかどうかは知らないが。

追記)・・・・上記は間違い。溜まったイベントを処理しないとウインドウに制御が渡らなくなることがあるみたいだ。こちらが正しいみたい。

Wx::get_app.dispatch while Wx::get_app.pending