PyQt5:最小化窗口后 QTimer 不同步(OSX)

Posted

技术标签:

【中文标题】PyQt5:最小化窗口后 QTimer 不同步(OSX)【英文标题】:PyQt5: QTimer out of sync after minimizing window (OSX) 【发布时间】:2015-06-02 19:20:54 【问题描述】:

我在使用 pyqt5 QTimer 类和 OSX 时遇到问题。

如果通过单击窗口左上角的黄色按钮将以下简单应用程序最小化,则应用程序会按预期移动到停靠栏的右下角,并且计时器每秒都会增加。

奇怪的是,在大约 2:30 分钟后,计时器会大大减慢计数,假设每 10 秒一次。我怀疑这与 OSX 下的“冻结”或“睡眠”模式有关?

我想要的是一个可靠的计时器,它每秒计数。 pyqt下有什么我遗漏的技巧吗?

---- 编辑----

如果窗口失去焦点,也会发生这种情况。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time

from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt, QTimer, pyqtSlot


class Main(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.seconds = 0
        self.init_ui()

    def init_ui(self):
        self.timer = QTimer()
        self.timer.setInterval(1000)
        self.timer.setTimerType(Qt.PreciseTimer)
        self.timer.timeout.connect(self.on_timer)
        self.timer.start()

    @pyqtSlot()
    def on_timer(self):
        self.seconds += 1
        print(time.strftime("%H:%M:%S", time.gmtime(self.seconds)))


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)

    screen = Main()
    screen.show()

    sys.exit(app.exec_())

我的系统的一些信息:

Python: 3.4.3
PyQt: 5.4.0
OSX: 10.9.5
uname -a: Darwin mac-pro 13.4.0 Darwin Kernel Version 13.4.0: Wed Mar 18 16:20:14 PDT 2015; root:xnu-2422.115.14~1/RELEASE_X86_64 x86_64

【问题讨论】:

目前我发现的是一个 ThreadsafeTimer 类表单github.com/robertsj/poropy/blob/master/pyqtgraph/…。但这仍然行不通。我认为这可能与我作为 GUI 程序员的技能有关。 【参考方案1】:

这可能与 OS X 的一项名为“AppNap”的功能有关,该功能将大大减少定时器触发,甚至在应用程序之间同步它们,以节省电池寿命。

您可以使用命令在每个应用程序的基础上通过命令行将其关闭

 defaults write <domain> NSAppSleepDisabled -bool YES

&lt;domain&gt; 是您的应用程序包标识符。你甚至可以通过子进程在你的应用程序中调用它——这就是我所做的。

虽然这不是一个理想的解决方案,但请考虑使用计时器。根据您的实际用例,可能还有其他方法可以解决此问题。

【讨论】:

谢谢@deets,我必须试试这个,但正如你所说,这不是一个理想的解决方案。但我担心这个问题没有理想的解决方案...... 只是让你知道,我的用例就像一个秒表,用于跟踪我正在进行的项目的时间。【参考方案2】:

除了@deets,这将是另一种可能的解决方案,它检查开始时间并使用增量来计算该开始时间的偏移量。至少它现在对我有用:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time
import os

from datetime import datetime

from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt, QObject, QTimer, QThread, pyqtSlot, pyqtSignal


class Main(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.ellapsed_sec = 0
        self.init_ui()

    def init_ui(self):
        self.timer = QTimer()
        self.timer.setInterval(1000)
        self.timer.setTimerType(Qt.PreciseTimer)
        self.timer.timeout.connect(self.on_timer)

        self.timestamp_start = datetime.now()

        self.timer.start(1000)

    @pyqtSlot()
    def on_timer(self):
        self.ellapsed_sec += 1

        delta = datetime.now() - self.timestamp_start
        delta = delta.total_seconds()
        if self.ellapsed_sec != delta:
            print('Using delta', delta)
            self.ellapsed_sec = delta

        print(time.strftime("%H:%M:%S", time.gmtime(self.ellapsed_sec)))


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)

    screen = Main()
    screen.show()

    sys.exit(app.exec_())

【讨论】:

以上是关于PyQt5:最小化窗口后 QTimer 不同步(OSX)的主要内容,如果未能解决你的问题,请参考以下文章

如何设置 PyQt5 Qtimer 在指定的时间间隔内更新?

PyQt5编程(10):窗口的最小化与最大化

PyQt5系列教程定时器QTimer的使用

七.PyQt5定时器QTimer的使用

PyQt5 笔记(04):主窗口卡死问题

PyQt5-Qt Designer窗口操作