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,但是关于这个主题的文档对我来说几乎是不可读的。我想知道最好的方法是什么:PyO​​penGL、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 以固定速率刷新的主要内容,如果未能解决你的问题,请参考以下文章

预定执行器:以固定速率轮询结果,如果超时或结果有效则退出

Gui(pyqt5)滞后很多,然后python崩溃

简单 Python 快乐之旅之:Python 基础语法之 GUI 专题

Python3 以网络摄像头 fps 处理和显示网络摄像头流

更新tkinter标签以在我的python GUI上一次显示一行文本文件

python Tkinter GUI 串口通信 显示。