我需要在按下按钮时执行一些操作。我该怎么做?

我的版本是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”后继续运行)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top