كيف تفعل شيئا مرارا وتكرارا أثناء الضغط على الزر في gtk2hs؟

StackOverflow https://stackoverflow.com//questions/22059147

  •  23-12-2019
  •  | 
  •  

سؤال

أحتاج إلى القيام ببعض الإجراءات أثناء الضغط على الزر.كيف يمكنني فعل ذلك؟

لدي الإصدار 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" مرة أخرى).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top