Issue
Below is a simple Qt for Python (PySide6) application that tries to count the number of times a slot gets called in one second:
import time
from PySide6.QtCore import *
from PySide6.QtTest import *
from PySide6.QtWidgets import *
class MainWindow(QWidget):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.resize(400, 300)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.sheep_number = 0
self.timer = QTimer()
self.timer.timeout.connect(self.count_sheep)
self.counted_sheep_label = QLabel()
self.layout.addWidget(self.counted_sheep_label) # comment out this line to see the bug
@Slot()
def count_sheep(self):
self.sheep_number += 1
self.counted_sheep_label.setText(f"Counted {self.sheep_number} sheep.")
if __name__ == "__main__":
app = QApplication([])
main_window = MainWindow()
main_window.show()
main_window.timer.start()
then = time.time()
QTest.qWait(1000)
main_window.timer.stop()
t = time.time() - then
print(t, main_window.sheep_number)
The code brings up a GUI and leaves it on the screen for 1 second. It then prints the time that elapsed (according to Python rather than Qt) and number of calls to the slot. When I run this on my laptop, I get 1.0010387897491455
and 7155
However, when I comment out the indicated line, I get 1.0011870861053467
88
.
I do not understand this behavior. Why would not drawing the GUI cause QTimer
to fire less often?
Solution
You have to be cautious about using a QTimer
with a zero interval. If you don't call a waiting function in the signal handler, it will result in a high CPU usage due to a busy loop. (It can be nearly 100%.)
In MacOS, you can see that by calling the app.exec()
without calling the main_window.timer.stop()
.
And why does the QTest.qWait()
not result in a high CPU usage on MacOS? The QTest::qWait()
calls the QCoreApplication::processEvents()
, which runs a loop calling the QEventDispatcherCoreFoundation::processEvents()
, which calls CFRunLoopRunInMode()
one more time and returns false
. So, the QTest.qWait()
will call the QTestPrivate::qSleep()
less frequently if you update the UI in the signal handler. (Updating the UI may cause new events are enqueued into the event queue.)
I think this behavior in MacOS is a side effect. What about reporting this here?
Answered By - relent95
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.