Kivy:如何在这种情况下正确使用 Clock.Schedule

Kivy: How to use Clock.Schedule properly in this instance

所以我正在编写一些代码,以在随机时间范围后通过虚拟键随机发送按键(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 是 运行 ning,程序不会关闭

一般来说,你应该避免在 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)