كيف تفعل شيئا مرارا وتكرارا أثناء الضغط على الزر في gtk2hs؟
سؤال
أحتاج إلى القيام ببعض الإجراءات أثناء الضغط على الزر.كيف يمكنني فعل ذلك؟
لدي الإصدار 0.12.4.
ص.س.:لسبب ما، 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")
لست متأكدًا مما إذا كان هذا آمنًا، حيث يبدو أنه من الممكن إطلاق حدث ButtonReleased قبل تسجيل killThread.قد يكون استخدام 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، وهو كائن "مهلة" (راجع timeoutAdd في الوحدة النمطية System.Glib.MainLoop في المستندات) و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 objectDestroy mainQuit" على النافذة يدمر النافذة بشكل صحيح ويوقف حلقة Gtk الرئيسية (الإصدار الخاص بك لم يدمر المؤقتات في GHCi، لقد استمروا في العمل بعد استدعاء "main" مرة أخرى).