I am trying to get the basics of QT5 threading. This is my first attempt, combined from various sources:
import sys
from time import sleep
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QGridLayout
from PyQt5.QtCore import QThread, QObject
'''
Traceback (most recent call last):
File "threads.py", line 68, in <module>
main(sys.argv)
File "threads.py", line 63, in main
window = Window()
File "threads.py", line 15, in __init__
self.initUi()
File "threads.py", line 28, in initUi
self.worker.moveToThread(self.thread)
AttributeError: 'NoneType' object has no attribute 'moveToThread'
Press any key to continue . . .
'''
class Window(QWidget):
def __init__(self):
super().__init__()
self.initUi()
self.low = 0
self.high = 100
self.show()
def initUi(self):
self.thread = QThread()
self.worker = Worker(self)
self.worker.moveToThread(self.thread)
self.thread.start()
self.button = QPushButton(
'Start long running task')
self.layout = QGridLayout()
self.layout.addWidget(self.button, 0, 0)
self.setLayout(self.layout)
def Worker(QObject):
def __init__(self, parent):
super(Worker, self).__init__(parent)
do_work()
def do_work(self):
for _ in range(20):
print('running . . .')
sleep(2)
def main(args):
app = QApplication(args)
window = Window()
sys.exit(app.exec_())
if __name__ == '__main__':
main(sys.argv)
I have included the error I get in the code snippet. From online articles i learned that in PyQt5 I shouldn't subclass QThread.
stumbled upon this question while reviewing QThreads , amazing how fast I forget stuff, that's why I am posting an upgraded version of @ellyansec answer, need to keep it to avoid having to start from scratch next time too. I am sure the way I stop the QThreads is suboptimal , please feel free to make it better, my code:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QGridLayout
from PyQt5.QtCore import QThread, QObject, pyqtSlot, pyqtSignal
import threading
class Window(QWidget):
button_pushed = pyqtSignal()
def __init__(self):
super().__init__()
self.initUi()
self.low = 0
self.high = 100
self.show()
def initUi(self):
self.thread = QThread()
self.worker = Worker()
self.worker.moveToThread(self.thread)
self.button_pushed.connect(self.worker.do_work)
self.thread.finished.connect(self.thread.deleteLater)
self.thread.start()
self.button = QPushButton(
'Start long running task')
self.button_2 = QPushButton('Stop QThread')
self.button.clicked.connect(self.start)
self.button_2.clicked.connect(self.stop_thread)
self.layout = QGridLayout()
self.layout.addWidget(self.button, 0, 0)
self.layout.addWidget(self.button_2, 50, 0)
self.setLayout(self.layout)
self.cnt = 0
def start(self):
self.cnt += 1
print('button pushed ' + str(self.cnt) + ' time ')
self.button_pushed.emit()
def stop_thread(self):
self.thread.quit()
self.thread.wait()
class Worker(QObject):
def __init__(self, parent=None):
QObject.__init__(self, parent=parent)
@pyqtSlot()
def do_work(self):
for k in range(3):
print('running . . .' + str(threading.get_ident())+'.......'+str(k+1))
QThread.sleep(2)
print('done !!!')
def main(args):
app = QApplication(args)
window = Window()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main(sys.argv)