Come fare qualcosa ripetutamente mentre il pulsante è premuto in GTK2HS?
Domanda
Devo fare qualche azione mentre viene premuto il pulsante.Come posso farlo?
Ho la versione 0.12.4.
p.S.:
Per qualche motivo, onButtonActivate
in
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
.
Non fare nulla.
.
Inoltre, è bello andare, se l'azione verrà eseguita ripetutamente mentre premeva un po 'di tastiera sulla tastiera.
Soluzione
Secondo il Documenti onbuTonactivate è ammortizzato in modo da probabilmente non dovresti usarlo.Sto avendo problemi a trovare il modo corretto, ci sono probabilmente alcuni segnali generici da qualche parte che dovresti usare.Puoi provare la mia soluzione che utilizza igiene e onrelease (queste sono anche note come ammortizzate).Potresti fare come suggerito nel commento e alla forcella un filo:
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
.
Quindi riscrivi il tuo principale da fare:
whilePressed but (putStr "A")
.
Non sono sicuro che questo sia al sicuro, come sembra che potrebbe essere possibile per l'evento abbottonato da sparare prima che il killthread sia registrato.Potrebbe essere più sicuro usare 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
.
Purtroppo non ho compilato o testato il codice Sine non posso installare GTK su questo computer, ma fammi sapere se hai problemi.
Altri suggerimenti
Questo utilizza un tagglebutton, un oggetto "timeout" (vedere TimeoutaDD nel sistema del modulo.glib.mainloop nei documenti) e un IOREF.Un timer viene avviato quando viene premuto il tagglebutton, ma solo se nessun altro timer è attualmente in esecuzione (è lo scopo dello IOREF).Se il pulsante viene rilasciato, il timer viene interrotto.La funzione di callback del timer ritorna IO FALSE per interrompere e distruggere l'oggetto 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
.
Il modo preferito di registrazione dei callback del segnale utilizza "On".Si noti inoltre che "On Window ObjectDestroy Mainquit" distrugga correttamente la finestra e interrompe il ciclo principale GTK (la versione non distrugge i timer in GHCI, continuavano a correre dopo aver chiamato nuovamente "Main").