Haskell でイベント駆動型プログラムを作成する方法を理解するためだけに、おもちゃのアプリケーションを作成しようとしています。私がやろうとしているのは、キーが押されるたびに前方に移動するキャンバスに線を引くことです (つまり、テキスト エディターの原始的なカーソルのようなものです)。
私の問題は、ユーザーがキーを押した回数を数える最良の方法を理解できないことです。明らかに、命令型プログラムのようにグローバル変数を使用することはできないため、おそらくコールスタックで状態を渡す必要がありますが、GTK では、各イベントハンドラーが返された後、実行がメインループに降ります。メイン ループを制御する 変更されたグローバル状態を 1 つのイベント ハンドラーから渡す方法がわかりません。では、あるイベント ハンドラーが別のイベント ハンドラーに状態を渡すにはどうすればよいのでしょうか。
ここでは、キーボード イベントが 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