¿Cómo hacer algo repetidamente mientras se presiona el botón en GTK2HS?
Pregunta
Necesito hacer alguna acción mientras se presiona el botón.¿Cómo puedo hacerlo?
Tengo la versión 0.12.4.
p.S.:
Por alguna razón, onButtonActivate
en
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
No hagas nada.
Además, es bueno ir, si la acción se hará repetidamente mientras presiona alguna tecla en el teclado.
Solución
De acuerdo con la docs onbuttonactivate se deprecia, por lo que probablemente no deberías usarlo.Sin embargo, tengo problemas para encontrar la forma correcta, probablemente hay algunas señales genéricas en algún lugar que debe usar.Puede probar mi solución que use opresionada y onRelease (estos también se observan como depreciados).Podría hacer lo que se sugiere en el comentario y la horquilla un hilo:
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
luego reescribe a su principal que hacer:
whilePressed but (putStr "A")
No estoy seguro de si esto es seguro, ya que parece posible que pueda ser despedido para que el evento de Botón se le haya registrado antes de que KillThread se registre.Puede ser más seguro usar un iERef:
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
Lamentablemente, no he compilado ni probado el código sine, no puedo instalar GTK en esta computadora, pero avíseme si tiene algún problema.
Otros consejos
Esto utiliza un objeto ToggleButton, un "Tiempo de espera" (consulte el tiempo de tiempo en el sistema Module.glib.mainloop en los documentos) y un iERef.Se inicia un temporizador cuando se presiona el ToggleButton, pero solo si no se está ejecutando ningún otro temporizador (ese es el propósito de la IOREF).Si se libera el botón, el temporizador se detiene.La función de devolución de llamada del temporizador devuelve IO False para detener y destruir el objeto TEMPORTER.
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
La forma preferida de registrar las devoluciones de llamada de señal está usando "ON".También tenga en cuenta que "On Window ObjectDestroy Mainquit" destruye correctamente la ventana y detiene el bucle principal de GTK (la versión no destruyó los temporizadores en GHCI, siguieron funcionando después de llamar "Main" nuevamente).