python - Simple application of QThread -


i getting grip on qthread in order not lock gui, while performing possibly longer threads in background. trying practice write simple application: countdown timer can start clicking on button "start", thereby initiating countdown loop, can pause clicking on button "pause".

i want in "proper way" of using qthread (explained over here), i.e. subclassing qobject , attach instance of subclass qthread via movetothread. did gui qtdesigner , modified far (from other examples on net) in python:

from pyqt4 import qtgui, qtcore pyqt4.qtcore import qthread, signal  import time, sys, mydesign  class someobject(qtcore.qobject):      def __init__(self, lcd):         super(self.__class__, self).__init__()         self.lcd = lcd         self.looping = true     finished = qtcore.pyqtsignal()     def pauseloop(self):         print "hello?"         self.looping = false      def longrunning(self):         count = 10         self.lcd.display(count)         while count > 0 , self.looping:             time.sleep(1)             count -= 1             self.lcd.display(count)         self.finished.emit()  class threadingtutorial(qtgui.qmainwindow, mydesign.ui_mainwindow):     def __init__(self):         super(self.__class__, self).__init__()         self.setupui(self)          #an instance of someobject gets attached         #an instance of wrapper class qthread()          #objthread wrapper object instance of         # self-defined class someobject         self.objthread = qtcore.qthread()         self.obj = someobject(self.lcdnumber)         self.obj.movetothread(self.objthread)         #connect signals         self.obj.finished.connect(self.objthread.quit)         self.objthread.started.connect(self.obj.longrunning)         self.startcountdown.clicked.connect(self.objthread.start)         self.pausebutton.clicked.connect(self.obj.pauseloop)   if __name__ == "__main__":     app = qtgui.qapplication(sys.argv)     form = threadingtutorial()     form.show()     app.exec_() 

the gui not locked function pauseloop() gets executed after loop finished. how have in order accomplish goal able pause loop in longrunning()?

thx in advance!

update:

with of steve's , three_pineapples's remarks, come following solution using inner event loop of objthread:

from pyqt4 import qtgui, qtcore pyqt4.qtcore import qthread, signal, qtimer  import time, sys, mydesign  class someobject(qtcore.qobject):      def __init__(self):         super(self.__class__, self).__init__()         self.looping = true         self.count = 10         self.timer = qtimer(self)         self.timer.start(1000)         self.connect(self.timer, signal("timeout()"), self.longrunning)      finished = qtcore.pyqtsignal()     iterated = qtcore.pyqtsignal()     def pauseloop(self):         self.looping = false      def longrunning(self):         if self.count > 0 , self.looping:             self.count -= 1             self.iterated.emit()         else:             self.finished.emit()# sends signal stopping event loop  class threadingtutorial(qtgui.qmainwindow, mydesign.ui_mainwindow):     def __init__(self):         super(self.__class__, self).__init__()         self.setupui(self)           #an instance of someobject gets attached         #an instance of wrapper class qthread()          #objthread wrapper object instance of         # self-defined class someobject         self.objthread = qtcore.qthread()         self.obj = someobject()         self.lcdnumber.display(self.obj.count)         self.obj.movetothread(self.objthread)         #connect signals         self.obj.finished.connect(self.objthread.quit)         self.obj.iterated.connect(lambda: self.lcdnumber.display(self.obj.count))         self.objthread.started.connect(self.obj.longrunning)         self.startcountdown.clicked.connect(self.objthread.start)                 self.pausebutton.clicked.connect(self.obj.pauseloop)   if __name__ == "__main__":     app = qtgui.qapplication(sys.argv)     form = threadingtutorial()     form.show()     app.exec_() 

this happening because tell qt run code someobject object in single thread. in code, have 2 threads, main gui thread, , self.objthread. pauseloop() called in same thread longrunning(), means longrunning() must complete before pauseloop() can run. instead, need call pauseloop() different thread, not self.objthread.

note when start changing data 2 different threads (your main thread , new thread), start run race conditions. since you're setting 1 boolean variable, you'll fine, it's keep in mind.

edit: pointed out in comment three_pineapples, accessing gui objects (ex: qwidget) should done in main gui thread. show how work, have updated answer use signals update lcd in gui thread instead of printing value stdout. added code print out current thread @ different sections.

from pyside import qtgui, qtcore pyside.qtcore import qthread, signal  import time, sys  class someobject(qtcore.qobject):     updatecounter = qtcore.signal(int)     finished = qtcore.signal()     def __init__(self):         super(self.__class__, self).__init__()         self.looping = true     def pauseloop(self):         self.looping = false         print 'pause loop: '+str(qthread.currentthreadid())     def longrunning(self):         print 'long running: '+str(qthread.currentthreadid())         count = 10         while count > 0 , self.looping:             count -= 1             self.updatecounter.emit(count)             time.sleep(1)         self.finished.emit()  class threadingtutorial(qtgui.qwidget):     def __init__(self):         super(self.__class__, self).__init__()         #         self.thislayout = qtgui.qvboxlayout(self)         self.startcountdown = qtgui.qpushbutton('start', self)         self.pausebutton = qtgui.qpushbutton('stop', self)         self.lcd = qtgui.qlabel('', self)         self.thislayout.addwidget(self.startcountdown)         self.thislayout.addwidget(self.pausebutton)         self.thislayout.addwidget(self.lcd)         #         print 'main gui thread: '+str(qthread.currentthreadid())         self.objthread = qtcore.qthread()         self.obj = someobject()         self.obj.movetothread(self.objthread)         self.obj.updatecounter.connect(self._updatetimer)         #         self.obj.finished.connect(self.objthread.quit)         self.objthread.started.connect(self.obj.longrunning)         self.startcountdown.clicked.connect(self.objthread.start)         self.pausebutton.clicked.connect(self._stoptimer)     def _stoptimer(self):         self.obj.pauseloop()     def _updatetimer(self, num):         self.lcd.settext(str(num))         print 'update timer: '+str(qthread.currentthreadid())   if __name__ == "__main__":     app = qtgui.qapplication(sys.argv)     form = threadingtutorial()     form.show()     app.exec_() 

example output:

main gui thread: 3074717376 long running: 3034471232 update timer: 3074717376 update timer: 3074717376 update timer: 3074717376 update timer: 3074717376 update timer: 3074717376 update timer: 3074717376 pause loop: 3074717376 

Comments

Popular posts from this blog

c++ - llvm function pass ReplaceInstWithInst malloc -

java.lang.NoClassDefFoundError When Creating New Android Project -

Decoding a Python 2 `tempfile` with python-future -