Python GUI 以固定速率刷新
Posted
技术标签:
【中文标题】Python GUI 以固定速率刷新【英文标题】:Python GUI refreshing at a fixed rate 【发布时间】:2020-11-17 00:34:42 【问题描述】:我对此感到很困惑。我需要创建一个基于 Python 的 GUI,它应该以固定的速率更改对象。理想情况下,此频率应为 60 Hz(显示器刷新率)。
到目前为止,我有一个 PyQt GUI,它显示我想要的内容,由一个 QThread 控制,它监视经过的时间并在 0.016 秒(理想情况下为 60 Hz)后将 PyQtSignals 发送到主 GUI 以更新内容。我的问题是 PyQt 信号持续几毫秒才能到达主 GUI,因此我无法达到 60 Hz。而且帧率不是恒定的,而是在50-55ms之间变化……
这对我的应用程序来说太糟糕了。我想要的 GUI 应该以 固定 的速率更新。最好在 55Hz 下运行它而不会有偏差,因为 FPS 在 50-60 之间具有非恒定值。
所以我听说过 PyGame 和 PyOpenGL,但是关于这个主题的文档对我来说几乎是不可读的。我想知道最好的方法是什么:PyOpenGL、PyQt、PyGame、Unity?当然,如果有人能给我一些关于这个的信息,甚至是一个虚拟的 1 分钟脚本来演示要遵循的一般框架,我将不胜感激。
【问题讨论】:
为什么需要固定帧率?在视频游戏中,FPS 会根据系统资源和系统负载而变化,但游戏玩法保持不变。对于您的 gui 更新,您需要查看每一帧还是允许跳过(对于慢速系统)? PyGame 是低级库,您必须自己编写事件循环。它可能会尝试尽可能快地运行,并且您可以使用pygame.clock
将速度减慢到 60 FPS。但它不能保证固定速度 60 FPS。许多游戏使用循环,它不会尝试保持固定速率,而是使用dt
(“增量时间” - 用于绘制前一帧的时间)来计算对象在下一帧中的位置。这样即使 FPS 从 60 变为 15 再回到 60,它也可以流畅运行。我希望Unity
也不能保证固定速度,它使用dt
来制作流畅的动画。
在这种情况下,此 GUI 不打算成为视频游戏的一部分。这将是一项心理学研究的一部分。这就是为什么我需要固定费率:(
您的代码是否有 0.016 秒的显式延迟(即睡眠)?
@Mike67 是的!我知道前面几行会消耗一些毫秒,因此睡眠会使时间变化。我根据先前计算所消耗的时间使用变量 sleep 对其进行了纠正,但它一直在做同样的事情,所以我认为它是由 pyqtsignal 延迟引起的
【参考方案1】:
QTimer 似乎只有 1ms 的事件触发分辨率。我目前的解决方案是使用 PyQt5 QTimer 进行近似计时,然后使用 time.perf_counter() 进行精度:
class Widget1(Qwidget):
def __init__():
self.tick_timer = QTimer(self)
self.tick_timer.singleShot(16, self.tick)
self.t0 = time.perf_counter()
def tick(self):
t1 = time.perf_counter()
while (t1 - self.t0) > 0.016666:
t1 = time.perf_counter()
QApplication.processEvents()
self.t0 = t1
self.tick_timer.singleShot(16, self.tick)
self.update() # or repaint()
def paintEvent(self, event):
....
【讨论】:
以上是关于Python GUI 以固定速率刷新的主要内容,如果未能解决你的问题,请参考以下文章
简单 Python 快乐之旅之:Python 基础语法之 GUI 专题
Python3 以网络摄像头 fps 处理和显示网络摄像头流