ラベルとアクションのリストからボタンを生成するのに問題があります。IO が評価されていないこと (「on button buttonActivated アクション」) に関係していると確信していますが、それを修正する方法はわかりません。
Button を生成するために使用する (Label, Command) タプルのリストがあり、関連付けられている IO () アクションです。
「on button buttonActivated アクション」を呼び出す関数が呼び出されますが、ボタンはまだクリックを登録しません。
module GtkTest where
import qualified Data.Map as M
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Buttons.Button
import Graphics.UI.Gtk.Windows.Window
import Graphics.UI.Gtk.Layout.VBox
import Control.DeepSeq
type Command = String
type ButtonLabel = String
type ButtonAction = IO ()
type ButtonDesc = (ButtonLabel, Command)
data ButtonInfo = ButtonInfo {
buttonLabel :: ButtonLabel
, buttonAction :: ButtonAction
, buttonIo :: IO Button
}
genAction :: Command -> ButtonAction
genAction command = putStrLn ("Running: " ++ command)
genButton :: ButtonDesc -> ButtonInfo
genButton info = let (label, command) = info
in ButtonInfo label (genAction command) (buttonNewWithLabel label)
getButtonDescs :: IO [ButtonDesc]
getButtonDescs = return [("Ok", "ok"),
("Foo", "foo"),
("Bar", "bar")]
applyAction (ButtonInfo _ action io) = do
--This gets called
putStrLn "applying click handler"
button <- io
--But apparently not this
on button buttonActivated action
addIoToContainer container io = do
widget <- io
containerAdd container widget
main = do
initGUI
window <- windowNew
--These buttons do not work
buttonDescs <- getButtonDescs
buttons <- return $ map genButton buttonDescs
vbox <- vBoxNew True 0
_ <- sequence $ map ((addIoToContainer vbox) . buttonIo) buttons
_ <- sequence $ map applyAction buttons
_ <- containerAdd window vbox
-- This button works
button <- buttonNewWithLabel "Manually made"
on button buttonActivated $ genAction "Manual action"
containerAdd vbox button
onDestroy window mainQuit
widgetShowAll window
mainGUI
どんな助けでも大歓迎です。ありがとうございました。
編集:
chi の回答に従って、ButtonInfo データ型を IO を実行しないように更新し、最終的に IO [ButtonInfo] になり、アクションをバインドできるようになりました。
改訂されたソース (作業中):
module GtkTest where
import qualified Data.Map as M
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Buttons.Button
import Graphics.UI.Gtk.Windows.Window
import Graphics.UI.Gtk.Layout.VBox
import Control.DeepSeq
type Command = String
type ButtonLabel = String
type ButtonAction = IO ()
type ButtonDesc = (ButtonLabel, Command)
data ButtonInfo = ButtonInfo {
buttonLabel :: ButtonLabel
, buttonAction :: ButtonAction
, buttonWidget :: Button
}
genAction :: Command -> ButtonAction
genAction command = putStrLn ("Running: " ++ command)
genButton :: ButtonDesc -> IO ButtonInfo
genButton info = let (label, command) = info
in do
button <- (buttonNewWithLabel label)
return $ ButtonInfo label (genAction command) button
getButtonDescs :: IO [ButtonDesc]
getButtonDescs = return [("Ok", "ok"),
("Foo", "foo"),
("Bar", "bar")]
applyAction (ButtonInfo _ action widget) = do
putStrLn "applying click handler"
on widget buttonActivated action
addIoToContainer container io = do
widget <- io
containerAdd container widget
main = do
initGUI
window <- windowNew
buttonDescs <- getButtonDescs
buttons <- sequence $ map genButton buttonDescs
vbox <- vBoxNew True 0
_ <- sequence $ map ((containerAdd vbox) . buttonWidget) buttons
_ <- sequence $ map applyAction buttons
_ <- containerAdd window vbox
button <- buttonNewWithLabel "Manually made"
on button buttonActivated $ genAction "Manual action"
containerAdd vbox button
onDestroy window mainQuit
widgetShowAll window
mainGUI