Kivy活动安排得太早了



Python 3.7 Kivy 1.11.1 OSX 10.14.6

我正在编写一个 25 fps 的 Kivy 应用程序,该应用程序应该有一个 10 毫秒的快速事件循环。问题是循环的调用速度要快得多- 几乎是立即。有没有办法解决这个问题?这是我的测试代码:

from kivy.config import Config
Config.read("config.ini")
Config.set('graphics', 'maxfps', '25')
Config.set('kivy', 'kivy_clock', 'free_all')
Config.write()
from kivy.uix.relativelayout import RelativeLayout
from kivy.app import App
from time import time
from kivy.clock import Clock
from collections import deque
from numpy import median
class Screen(RelativeLayout):
durations_ms = deque(maxlen=100)
last_event_loop_time = time()
counter = 1
@staticmethod
def event_loop(dt):
duration_ms = (time() - Screen.last_event_loop_time) * 1000
Screen.durations_ms.append(duration_ms)
Screen.last_event_loop_time = time()
if Screen.counter == 0:
print("Interval time (ms) median: {0:.3f}, min: {1:.3f}, max: {2:.3f}"
.format(median(Screen.durations_ms), min(Screen.durations_ms), max(Screen.durations_ms)))
Screen.counter = (Screen.counter + 1) % 100
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
Clock.schedule_interval_free(self.event_loop, 0.010)

class TestApp(App):
def build(self):
return Screen()
if __name__ == "__main__":
TestApp().run()

输出为:

Interval time (ms) median: 0.035, min: 0.030, max: 1.431
Interval time (ms) median: 0.061, min: 0.030, max: 0.408
Interval time (ms) median: 0.037, min: 0.031, max: 0.551

你的问题引起了我的兴趣。我建议使用不同的方法来使用 Pythonsched模块来调度您的event_loop。下面是执行此操作的代码的修改版本:

from kivy.config import Config
Config.read("config.ini")
Config.set('graphics', 'maxfps', '25')
Config.set('kivy', 'kivy_clock', 'free_all')
Config.write()
from kivy.uix.relativelayout import RelativeLayout
from kivy.app import App
import sched
from time import time, sleep
from collections import deque
from numpy import median
class Screen(RelativeLayout):
durations_ms = deque(maxlen=100)
last_event_loop_time = time()
counter = 1
s = sched.scheduler(time, sleep)  # create the scheduler
def event_loop(self):
duration_ms = (time() - Screen.last_event_loop_time) * 1000
Screen.last_event_loop_time = time()
Screen.durations_ms.append(duration_ms)
if Screen.counter == 0:
print("Interval time (ms) median: {0:.3f}, min: {1:.3f}, max: {2:.3f}"
.format(median(Screen.durations_ms), min(Screen.durations_ms), max(Screen.durations_ms)))
Screen.counter = (Screen.counter + 1) % 100
# enter the next call to event_loop into the scheduler
Screen.s.enter(0.01, 1, self.event_loop)
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
# enter the first call to event_loop and start the scheduler
Screen.s.enter(0.01, 1, self.event_loop)
Screen.s.run()

class TestApp(App):
def build(self):
return Screen()
if __name__ == "__main__":
TestApp().run()

请注意,这会在主线程上运行event_loop。如果您的event_loop正在进行 GUI 更新,这很好,否则非常糟糕。

如果您的 GUI 因此在主线程上运行而受到影响,您可以使用此版本在另一个线程上运行它:

from kivy.config import Config
Config.read("config.ini")
Config.set('graphics', 'maxfps', '25')
Config.set('kivy', 'kivy_clock', 'free_all')
Config.write()
from kivy.uix.relativelayout import RelativeLayout
from kivy.app import App
import sched
from time import time, sleep
from collections import deque
from numpy import median
import threading

class Screen(RelativeLayout):
durations_ms = deque(maxlen=100)
last_event_loop_time = time()
counter = 1
def run_event_loop(self):
self.s = sched.scheduler(time, sleep)
self.s.enter(0.01, 1, self.event_loop)
self.s.run()
def event_loop(self):
duration_ms = (time() - Screen.last_event_loop_time) * 1000
Screen.last_event_loop_time = time()
Screen.durations_ms.append(duration_ms)
if Screen.counter == 0:
print("Interval time (ms) median: {0:.3f}, min: {1:.3f}, max: {2:.3f}"
.format(median(Screen.durations_ms), min(Screen.durations_ms), max(Screen.durations_ms)))
Screen.counter = (Screen.counter + 1) % 100
self.s.enter(0.01, 1, self.event_loop)
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
threading.Thread(target=self.run_event_loop, daemon=True).start()

class TestApp(App):
def build(self):
return Screen()
if __name__ == "__main__":
TestApp().run()

最新更新