1

私はHaskellの経験があまりなく、Gtk2Hを使い始めたばかりなので、これはばかげた質問かもしれません。

次のLineタイプを定義しています。

type Coord = (Int,Int)
type Line = (Coord,Coord)

Lineそして、にsのリストを描画する関数がありますDrawingArea。問題は、この関数がすべてのLinesを同時に描画することですが、2つの秒の間に少し遅れて一度に1つずつ描画したいと思いLineます。

render :: [Line] -> IO ()
render lines =
  do initGUI
     win <- windowNew
     windowSetTitle win "Animation"
     win `onDestroy` mainQuit

     can <- drawingAreaNew
     can `onSizeRequest` return (Requisition 400 400)
     can `onExpose` drawCanvas lines can

     but <- buttonNewWithLabel "Quit"
     but `onClicked` mainQuit
     hbox <- hBoxNew False 0
     boxPackStart hbox but PackRepel 150

     vbox <- vBoxNew False 5
     containerAdd vbox can
     containerAdd vbox hbox
     containerAdd win vbox

     widgetShowAll win
     mainGUI

この関数は、DrawingAreaが公開されたときに呼び出されます。

drawCanvas :: [Line] -> DrawingArea -> event -> IO Bool
drawCanvas lines can _evt =
  do dw <- widgetGetDrawWindow can
     drawWindowClear dw
     gc <- gcNew dw
     mapM_ (\(a,b) -> drawLine dw gc a b) lines
     return True

StateTまだ描画されていないものを追跡するためにを使用することを検討しましたLineが、アニメーションの実装方法がわかりません。widgetShowAll状態を変更してから毎回呼び出す場合でも、mainGUIが呼び出されるまでウィンドウは表示されません。

drawCanvasどういうわけか描画を処理しながら、状態を継続的に更新する新しいスレッドを作成することは可能ですか?もしそうなら、誰かがそのような行動の例を教えてくれませんか?それとももっと良いアプローチがありますか?

4

1 に答える 1

3

Gtk2Hsを使用すると、定期的に関数を呼び出す「タイマー」を設定できます。だから私は次のことをします:

  • ほとんどのGtk2HはIOモナドで発生するため、IORefまたはMVarを使用してアニメーションの状態を保存し、任意の場所で変更します。
  • timeoutAdd次のように、mainGUIの前に呼び出しを追加しますtimeoutAdd (update can lines) 100。100ミリ秒ごとに実行されるタイマーを設定し、アニメーション状態をパラメーターとして、DrawingAreaとIORef/MVarを使用して新しい関数「update」を呼び出します。
  • 関数「更新」で、アニメーションの状態を変更して呼び出しwidgetQueueDraw can、描画領域が再露出されるようにします。これは、exposureイベントに接続されているため、自動的に「drawCanvas」を呼び出します。「更新」はIOブール値を返す必要があります。Falseを返すと、タイマーが停止します。
  • アニメーションの状態を更新するには、タプルを使用します。最初の要素は描画される線を格納し、2番目の要素は他の線のリストを格納します。

アニメーションの状態と描画を別々の関数で更新することには意味があると思います。

于 2013-01-02T09:44:26.467 に答える