如何在 gtk2hs 中按下按钮时重复执行某些操作?
题
我需要在按下按钮时执行一些操作。我该怎么做?
我的版本是0.12.4。
P。S:因为某些原因, onButtonActivate
在
import Graphics.UI.Gtk
import Control.Concurrent
main = do
initGUI
window <- windowNew
but <-buttonNewWithLabel "Write A"
onButtonActivate but $ do
putStr "A"
threadDelay 1000000
return()
containerAdd window but
widgetShowAll window
onDestroy window mainQuit
mainGUI
不要做任何事。
另外,如果按下键盘上的某个键时会重复执行操作,那就很好了。
解决方案
根据 文档 onButtonActivate 已被弃用,因此您可能不应该使用它。不过,我无法找到正确的方法,可能在某个地方有一些您应该使用的泛型信号。您可以尝试我的使用 onPressed 和 onRelease 的解决方案(这些也被标记为已贬值)。您可以按照评论中的建议进行操作并分叉一个线程:
import Control.Concurrent (forkIO, killThread, threadDelay)
import Control.Monad (void, when)
whilePressed button action = do
onPressed button $ do
threadId <- forkIO go
onReleased button (killThread threadId)
where
go = do
action
threadDelay 1000000
go
然后重写你的主要任务:
whilePressed but (putStr "A")
我不确定这是否安全,因为似乎在注册killThread之前可能会触发buttonReleased事件。使用 IORef 可能更安全:
import Data.IORef
whilePressed button action = do
isPressed <- newIORef False
onPressed button $ do
writeIORef isPressed True
void $ forkIO $ go isPressed
onReleased button (writeIORef isPressed False)
where
go isPressed = do
c <- readIORef isPressed
when c $ do
action
threadDelay 1000000
void $ forkIO $ go isPressed
不幸的是,我还没有编译或测试代码,因为我无法在这台计算机上安装 GTK,但如果您有任何问题,请告诉我。
其他提示
这使用了 ToggleButton、“超时”对象(请参阅文档中 System.Glib.MainLoop 模块中的 timeoutAdd)和 IORef。当按下 ToggleButton 时,计时器就会启动,但前提是当前没有其他计时器正在运行(这就是 IORef 的目的)。如果松开按钮,计时器就会停止。计时器的回调函数返回 IO False 以停止并销毁计时器对象。
import Graphics.UI.Gtk
import Data.IORef
import Control.Monad(void, when)
action but idle = do
butDown <- get but toggleButtonActive
if butDown
then do
putStrLn "A"
writeIORef idle False
return True
else do
writeIORef idle True
return False
main = do
initGUI
window <- windowNew
but <-toggleButtonNewWithLabel "Write A"
idle <- newIORef True
on but toggled $ do
butDown <- get but toggleButtonActive
isIdle <- readIORef idle
when (butDown && isIdle) $ void $ timeoutAdd (action but idle) 1000
containerAdd window but
widgetShowAll window
on window objectDestroy mainQuit
mainGUI
注册信号回调的首选方法是使用“on”。另请注意,“on window objectDestroy mainQuit”正确地销毁了窗口并停止了 Gtk 主循环(您的版本没有销毁 GHCi 中的计时器,它们在再次调用“main”后继续运行)。
不隶属于 StackOverflow