我正在尝试制作一个玩具应用程序,只是为了让我的头了解如何在Haskell中编写事件驱动的程序。我想要做的是在每次按下按键时向前移动一个画布(因此它是文本编辑器中的原始光标)。如何在gtk2hs中的事件处理程序之间传递状态
我的问题是我无法计算出用户按下某个键的次数的最佳方法。显然,我不能像我在一个命令式程序中那样使用全局变量,所以大概我需要在调用堆栈上传递状态,但是在GTK中,每个事件处理程序返回后执行都会下降到主循环中,并且由于我不控制主循环我看不出我如何从一个事件处理程序传递更改后的全局状态。那么,一个事件处理程序如何将状态传递给另一个事件处理程序
我在这里有一种部分解决方案,其中键盘事件re-curries myDraw并将其设置为新的事件处理程序。我不确定这个解决方案是否可以扩展,或者哪怕这是个好主意。
这个问题最好的解决方案是什么?
import Graphics.UI.Gtk
import Graphics.Rendering.Cairo
main :: IO()
main= do
initGUI
window <- windowNew
set window [windowTitle := "Hello World",
windowDefaultWidth := 300, windowDefaultHeight := 200]
canvas <- drawingAreaNew
containerAdd window canvas
widgetShowAll window
draWin <- widgetGetDrawWindow canvas
canvas `on` exposeEvent $ do liftIO $ renderWithDrawable draWin (myDraw 10)
return False
window `on` keyPressEvent $ onKeyboard canvas
window `on` destroyEvent $ do liftIO mainQuit
return False
mainGUI
onKeyboard :: DrawingArea -> EventM EKey Bool
onKeyboard canvas = do
liftIO $ do drawWin <- widgetGetDrawWindow canvas
canvas `on` exposeEvent $ do liftIO $renderWithDrawable drawWin (myDraw 20)
return False
widgetQueueDraw canvas
return False
myDraw :: Double -> Render()
myDraw pos = do
setSourceRGB 1 1 1
paint
setSourceRGB 0 0 0
moveTo pos 0
lineTo pos 20
stroke