Timer in child theme in PySide
First, I am very new to Python and Pyside. To improve self-improvement a bit, I'm trying to get QTimer to execute every second on a child thread of my PySide program (for now, I just want it to print “hello!” To the terminal every second without freezing the main window).
I tried to convert the example I found on the Qt Wiki from C ++ to Python / PySide, but since I don't really know C ++ I'll assume I converted it incorrectly and why it doesn't work as expected.
Currently, the doWork () function only works once, and then never again. What am I doing wrong? Is there a better way to execute a function every second in PySide without freezing the main window?
Here's the code (I've removed the main window code to increase clarity):
from PySide import QtGui from PySide import QtCore from client_gui import Ui_MainWindow statsThread = QtCore.QThread() class MainWindow(QtGui.QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) #setup GUI self.setupUi(self) #start thread to update GUI self.statsThread = updateStatsThread() self.statsThread.start(QtCore.QThread.TimeCriticalPriority) class updateGuiWithStats(QtCore.QObject): def Worker(self): timer = QtCore.QTimer() timer.timeout.connect(self.doWork()) timer.start(1000) def doWork(self): print "hi!" class updateStatsThread (QtCore.QThread): def run(self): updater = updateGuiWithStats() updater.Worker() self.exec_() if __name__ == '__main__': app = QtGui.QApplication(sys.argv) frame = MainWindow() frame.show() sys.exit(app.exec_())
source to share
@Masci already pointed out the fix you need for yours
, but I see more problems than just that.
No need to create a global QThread that is never used:
statsThread = QtCore.QThread()
Your QTimer is garbage collected right away because it was created without a parent and you are not saving it in your class. This is why even after you fix the timer connection it still won't work ... Try:
class UpdateGuiWithStats(QtCore.QObject): def startWorker(self): self.timer = QtCore.QTimer() self.timer.timeout.connect(self.doWork) self.timer.start(1000)
Also, use UpperCase for the first letter of the classes and camelCase for the methods. You are doing a mixture of both.
A couple of notes based on this link you provided, your example and other comments here ... You can only use QTimer as a solution if yours is
very light and won't block your main event loop with a bunch of data crunching, sleeping, etc. .d. If so,
you will need to move to QThread, as your example does. But at this point there is no need to use the event loop and QTimer in a separate class that calls its own work. All this can be combined into one class, for example:
class UpdateStatsThread(QtCore.QThread): def __init__(self, parent=None): super(UpdateStatsThread, self).__init__(parent) self._running = False def run(self): self._running = True while self._running: self.doWork() self.msleep(1000) def stop(self, wait=False): self._running = False if wait: self.wait() def doWork(self): print "hi!"
source to share
in the classroom
it should be
You are connecting the timeout signal to
(method return value
) and I think this is why it is only executed once:
called during connection and nomore. When making connections, remember to include the function name (in Pythonics words, the callable), not the function call.
By the way, even if the above is a solution to your problem, you should avoid using streams as QTimer already does on its own. In the docs you linked , the first answer to the question is when should I not use streams? question: Timers.
source to share