Я пытаюсь создать игрушечное приложение, просто чтобы понять, как писать управляемые событиями программы на Haskell.То, что я пытаюсь сделать, это нарисовать линию на холсте, который перемещается вперед при каждом нажатии клавиши (так что это своего рода изначальный курсор в текстовом редакторе).
Моя проблема в том, что я не могуопределите, как лучше всего посчитать, сколько раз пользователь нажал клавишу.Очевидно, я не могу использовать глобальную переменную, как в императивной программе, так что, вероятно, мне нужно передать состояние в стеке вызовов, но при выполнении GTK происходит возврат в основной цикл после того, как возвращается каждый обработчик события, и так как я неЯ не вижу, как я могу передать измененное глобальное состояние из одного обработчика событий.Итак, как один обработчик события может когда-либо передавать состояние другому обработчику события?
У меня есть своего рода частичное решение, когда событие клавиатуры повторно каррирует 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