【问题标题】:Kivy: How to use Clock.Schedule properly in this instanceKivy:如何在这种情况下正确使用 Clock.Schedule
【发布时间】:2021-12-28 05:21:42
【问题描述】:

所以我正在编写一些代码,以在随机时间范围后通过虚拟键随机发送按键(5-10 秒仅用于测试目的)。我正在尝试添加 Clock.schedule_once,但是根据我现在的情况,它每秒都会触发,因为它卡在了一个 while 循环中。我一直在绞尽脑汁想弄清楚如何正确实施这一点,但我似乎无法想出什么办法,所以我正在与你们联系,看看你们是否可以提供任何意见可能的解决方案。

    def v_key_timer(self, timer, wnd):
        while timer > 0:
            vkey = self.char2key(self.get_char_key(randrange(1, 5)))
            intrvl = randrange(5, 10)  # Sets a random time between 1-4 minutes to do a keypress
            self.select_window(wnd)
            if (timer - intrvl) <= 0:
                win32api.keybd_event(vkey, win32api.MapVirtualKey(vkey, 0), 0, 0)  # Keypress Down
                time.sleep(.5)
                win32api.keybd_event(vkey, win32api.MapVirtualKey(vkey, 0), win32con.KEYEVENTF_KEYUP, 0)  # Keypress Up
                time.sleep(timer)
                timer = 0
            else:
                win32api.keybd_event(vkey, win32api.MapVirtualKey(vkey, 0), 0, 0)  # Keypress Down
                time.sleep(.5)
                win32api.keybd_event(vkey, win32api.MapVirtualKey(vkey, 0), win32con.KEYEVENTF_KEYUP, 0)  # Keypress Up
                time.sleep(intrvl)
                timer -= intrvl

我希望在日志运行中让用户输入他们希望运行的时间,并为其创建一个倒数计时器供用户查看,但在此之前,我需要更改此操作的方式我设置的当前计时器系统正在运行,我认为 Clock.Schedule 可能是最好的选择,因为现在,当 time.sleep 运行时,程序不会关闭。

【问题讨论】:

    标签: python kivy


    【解决方案1】:

    一般而言,您应该避免在 kivy 应用程序中使用 time.sleep(),因为它会冻结事件处理例程。

    这是我基于两个预定工作的建议。简而言之,按键作业在随机时间之后安排一次,并且它会无限期地重新安排自己。第二个调度作业负责停止按键作业。

    # main.py
    
    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.clock import Clock
    from datetime import datetime
    from random import randrange
    
    
    class Screens(ScreenManager):
        pass
    
    
    class MyScreen(Screen):
        # scheduled job instance
        v_key_timer_job = None
        # window name
        v_key_timer_window = None
    
        def v_key_timer(self, timer, wnd):
            self.v_key_timer_window = wnd
            if self.v_key_timer_job is None:
                print(f'Key timer for "{self.v_key_timer_window}" started for {timer} seconds')
                # update buttons state
                self.ids.start_button.disabled, self.ids.abort_button.disabled = True, False
                # schedule next key press
                self.v_key_timer_job = Clock.schedule_once(self.v_key_timer_do, randrange(5, 10))
                # schedule end of timer
                Clock.schedule_once(self.v_key_timer_end, timer)
    
        def v_key_timer_end(self, dt):
            if self.v_key_timer_job is not None:
                print('Key timer stopped')
                # update buttons state
                self.ids.start_button.disabled, self.ids.abort_button.disabled = False, True
                # unschedule v_key_timer_job
                self.v_key_timer_job.cancel()
                self.v_key_timer_job = None
    
        def v_key_timer_do(self, dt):
            print(f'\t{datetime.now().strftime("%Y-%m-%d %H:%M:%S")} Doing {self.v_key_timer_window} keypress')
            # vkey = self.char2key(self.get_char_key(randrange(5, 10)))
            # self.select_window(self.v_key_timer_window)
            # win32api.keybd_event(vkey, win32api.MapVirtualKey(vkey, 0), 0, 0)  # Keypress Down
            # win32api.keybd_event(vkey, win32api.MapVirtualKey(vkey, 0), win32con.KEYEVENTF_KEYUP, 0)  # Keypress Up
            # schedule next key press
            self.v_key_timer_event = Clock.schedule_once(self.v_key_timer_do, randrange(5, 10))
    
    
    class KeyTimer(App):
        pass
    
    
    KeyTimer().run()
    

    还有kv文件:

    # keytimer.kv
    
    Screens:
        MyScreen:
    
    <MyScreen>:
        BoxLayout:
            orientation: "vertical"
    
            BoxLayout:
                size_hint: 1, 0.1
                Label:
                    text: 'timer [s]'
                TextInput:
                    id: timer
                    text: '60'
            BoxLayout:
                size_hint: 1, 0.1
                Label:
                    text: 'wnd'
                TextInput:
                    id: wnd
                    text: 'window_name'
    
            Button:
                id: start_button
                text: "Start key timer"
                on_release: root.v_key_timer(int(timer.text), wnd.text)
            Button:
                id: abort_button
                disabled: True
                text: "Abort key timer"
                on_release: root.v_key_timer_end(None)
    

    【讨论】:

    • 我没回家看这个,不过谢谢你的回复!
    • 非常感谢您。我现在能够让它与 Clock.schedule_once 一起工作。这对学习很有帮助。
    猜你喜欢
    • 2020-08-06
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-02
    • 2013-11-21
    • 1970-01-01
    相关资源
    最近更新 更多