HaskellでTwitterクライアント開発blog(仮)

今すぐに挫折するかもしれない程度のモチベーションによるTwitterクライアント開発記

DrawingAreaにタイムラインを表示できた

前回(http://hshstter.hatenablog.com/entry/2012/04/12/232132)挑戦して解決しなかったDrawingArea更新の件が解決しました。

わかったことは、

(1)onExposeイベントにセットしたアクションは、drawWindowClearAreaExposeなどで再描画するとちゃんと実行される。

(2)たとえば、変数xに依存するアクションact(x)をonExposeイベントにセットして実行する場合、
act(a)をonExposeにセットして、act(b)を再度onExposeにセットして再描画しても、act(a)の結果が表示される。
→おそらく、2回目以降のonExposeの実行は無視される?(かなり怪しい。それ以外の問題があるのかもしれない)

なので、前回のようなコードではダメで、解決法として、 更新する可能性がある変数をIORefで持っておいて、drawWindowClearAreaExposeでonExposeにセットしたアクションが実行される際に表示するテキストをreadIORefで読み込み直す という実装にするとちゃんと更新されました。

つまりたとえば

str <- makeString
onExpose $ \_ -> do
drawString str

ではなく

onExpose $ \_ -> do
str <- readIORef stringRef
drawString str

とすれば、再描画時にDrawingArea内が変更されます。(変更したい場合は、ここで指定したstringRefの内容をwriteIORefで書き換えればよい)

タイムラインを追加する関数(addTimeline)/タイムラインを更新する関数(updateTimeline)を分け、タイムライン追加関数でonExposeイベントにタイムラインを表示し、更新はupdateTimeline関数でdrawWindowClearAreaExposeアクションを実行することで行うようにしました。

 

ただ、この実装のままだとちょっと問題があって、2つ以上タイムラインを表示させたい時(List, Mentionなど)に追加できないという問題があります。将来的にはそういう機能は付けたいので、GUIデータ型にある「タイムライン一覧」をIORefにし、onExposeでこの一覧を読み込んですべて表示する、という変更が必要になると思います。(その場合、addTimelineではonExposeイベントへのアクションの設定は行わず、GUIのタイムライン一覧への追加のみ行うようにすればいいですね)

 

それにしても、副作用ばかりでHaskellっぽくないコードができつつありますね……何とかしたいです。