警告
本节包含从C++自动翻译到Python的代码片段,可能包含错误。
计时器¶
如何在您的应用程序中使用Qt定时器。
QObject,所有Qt对象的基类,提供了Qt中的基本计时器支持。使用startTimer(),你可以启动一个计时器,并以毫秒为单位的间隔作为参数。该函数返回一个唯一的整数计时器ID。然后,计时器将定期触发,直到你显式调用killTimer()并传入该计时器ID。
您可以使用QBasicTimer来代替直接处理计时器ID。QBasicTimer是一个值类,RAII包装器,用于包装计时器ID。您可以使用start()启动计时器,并使用stop()停止它(后者在销毁时也会被调用)。要使用QBasicTimer,您必须在您的类中重新实现timerEvent()(该类必须是QObject的子类),并在那里处理计时器事件。
为了使此机制工作,应用程序必须在事件循环中运行。您可以使用QApplication::exec()启动事件循环。当计时器触发时,应用程序会发送一个QTimerEvent,并且控制流会离开事件循环,直到计时器事件被处理。这意味着当您的应用程序忙于执行其他操作时,计时器无法触发。换句话说:计时器的准确性取决于应用程序的粒度。
在多线程应用程序中,您可以在任何具有事件循环的线程中使用计时器机制。要从非GUI线程启动事件循环,请使用exec()。Qt使用对象的thread affinity来确定哪个线程将传递QTimerEvent。因此,您必须在对象的线程中启动和停止所有计时器;无法为另一个线程中的对象启动计时器。
定时器功能的主要API是QTimer。QTimer将间隔存储在一个有符号整数中,这限制了它支持的最大间隔为可以放入有符号整数的毫秒数(实际上,这大约是24天的时间)。
Qt 6.8 引入了 QChronoTimer 类。这两个类的主要区别在于 QChronoTimer 支持更大的时间间隔范围和更高的精度(std::chrono::nanoseconds)。对于 QTimer,支持的最大时间间隔为 ±24 天,而对于 QChronoTimer,则为 ±292 年。如果你只需要毫秒级的分辨率和 ±24 天的时间范围,可以继续使用 QTimer。
计时器的准确性取决于底层操作系统。Windows 2000的精度为15毫秒;我们测试过的其他系统可以处理1毫秒的间隔。
QChronoTimer 提供了常规的计时器,当计时器触发时会发出信号,并且继承自 QObject,因此它非常适合大多数 Qt 程序的所有权结构。通常的使用方式如下:
timer = QChronoTimer(1s, self) timer.timeout.connect(self.processOneThing) timer.start() timer = QChronoTimer(self) timer.timeout.connect(self.processOneThing) timer.setInterval(1s) timer.start()
QChronoTimer 对象被设置为 this 对象的子对象,这样当 this 被销毁时,计时器也会被销毁。接下来,timeout() 信号被连接到将执行工作的槽,计时器间隔可以传递给构造函数,或者稍后使用 setInterval() 设置。
QChronoTimer 还提供了用于单次计时器的静态函数。例如:
widget = MyWidget() QChronoTimer::singleShot(200ms, widget.updateCaption)
在这行代码执行200毫秒后,updateCaption()槽将被调用。
为了使QChronoTimer工作,您的应用程序中必须有一个事件循环;也就是说,您必须在某处调用exec()。只有在事件循环运行时,计时器事件才会被传递。
在多线程应用程序中,您可以在任何具有事件循环的线程中使用QChronoTimer。要从非GUI线程启动事件循环,请使用exec()。Qt使用计时器的thread affinity来确定哪个线程将发出timeout()信号。因此,您必须在其线程中启动和停止计时器;不可能从另一个线程启动计时器。
模拟时钟示例展示了如何使用QChronoTimer定期重绘小部件。从AnalogClock的实现来看:
def __init__(self, parent): super().__init__(parent) timer = QChronoTimer(1s, self) timer.timeout.connect(this, QOverload<>::of(&AnalogClock::update)) timer.start() ... ... setWindowTitle(tr("Analog Clock")) resize(200, 200)
每秒,QChronoTimer 将调用 QWidget::update() 槽来刷新时钟的显示。