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)
所以我正在编写一些代码,以在随机时间范围后通过虚拟键随机发送按键(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)