我在Haskell方面没那么有经验,我刚刚开始使用Gtk2Hs,所以这可能是一个愚蠢的问题。
我定义了以下Line
类型:
type Coord = (Int,Int)
type Line = (Coord,Coord)
我有一个函数可以在Line
上绘制DrawingArea
的列表。问题是这个函数同时绘制了所有Line
,但我想一次绘制一个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
以某种方式处理绘图?如果是这样,有人可以告诉我这种行为的一个例子吗?或者是否有更好的方法?
答案 0 :(得分:3)
Gtk2Hs允许设置定时调用函数的“定时器”。所以我会做以下事情:
timeoutAdd
的调用,如下所示:timeoutAdd (update can lines) 100
设置一个每100毫秒运行一次的计时器,并使用DrawingArea和IORef / MVar调用新函数“update”将动画状态作为参数。widgetQueueDraw can
,以便重新显示绘图区域。这将自动调用“drawCanvas”,因为它连接到expose事件。 “更新”必须返回IO Bool。返回False将停止计时器。我发现在单独的函数中更新动画的状态和绘图是有意义的。