Comment faire quelque chose à plusieurs reprises alors que le bouton est enfoncé dans gtk2hs?
Question
J'ai besoin de faire un peu d'action, tandis que le bouton est pressé.Comment puis-je le faire?
J'ai la version 0.12.4.
P.S.:Pour une raison quelconque, onButtonActivate
dans
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
ne pas faire n'importe quoi.
Aussi, il est bon d'aller, si une action va être fait à plusieurs reprises tout pressé quelques clés sur le clavier.
La solution
Selon l' docs onButtonActivate est amorti de sorte que vous ne devriez probablement pas l'utiliser.Je vais avoir du mal à trouver le bon chemin, bien que, il y a sans doute certains génériques signaux quelque part que vous devez utiliser.Vous pouvez essayer ma solution qui utilise onPressed et au relâchement (ceux-ci sont également considérés comme amortis).Vous pourriez le faire, comme le suggère le commentaire de la fourche et un fil:
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
Alors réécrire votre principal pour le faire:
whilePressed but (putStr "A")
Je ne sais pas si c'est sûr, même si, comme il semble qu'il pourrait être possible pour le buttonReleased événement pour être tiré avant killThread est enregistré.Il peut être prudent d'utiliser un 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
Malheureusement, je n'ai pas compilé ou mis à l'essai le code des sinus je ne peux pas installer GTK sur cet ordinateur, mais laissez-moi savoir si vous avez des questions.
Autres conseils
Il utilise un ToggleButton, un "délai d'attente" de l'objet (voir timeoutAdd dans le module Système.La Glib.MainLoop dans les docs) et un IORef.Un timer est démarré lorsque le ToggleButton est pressé vers le bas, mais seulement si aucun autre minuterie est actuellement en cours d'exécution (c'est le but de la IORef).Si le bouton est relâché, la minuterie est arrêtée.La minuterie la fonction de callback retourne IO Faux de s'arrêter et de détruire l'objet timer.
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
Le moyen privilégié de l'enregistrement du signal à l'aide de rappels est "sur".Notez également que "sur la fenêtre de objectDestroy mainQuit" correctement détruit la fenêtre et s'arrête le Gtk boucle principale (vous version n'a pas de détruire les compteurs à zéro dans GHCi, ils restent en cours d'exécution après l'appel de la "main" de nouveau).