Как передавать состояние между обработчиками событий в gtk2hs

Я пытаюсь сделать игрушечное приложение, просто чтобы понять, как писать программы, управляемые событиями в 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 
8
задан Gareth Charnock 14 March 2011 в 01:39
поделиться