Hi im trying to understand threading in pyqt5. Iv'e outlined the process i use currently. Is this the correct way or is there a better way? Note, i am a complete threading noob.
This is how i pass data from GUI object. For example a combobox has changed, i have a self.comboBox.activated.connect(comboBoxChanged) in GUI class and then that corresponding function sets SharedVars.comboBoxChanged = True and then in one of the threadloops i check and see if SharedVars.comboBoxChanged == True and if it is do self.updateOtherStuffWhenComboBoxChanged.emit(getData()) and SharedVars.comboBoxChanged = False
class SharedVars():
...
#This is my GUI class
class Ui_MainWindow(QThread, SharedVars):
def setupUi(self, MainWindow):
#self.table stuff
#this is the class i start threads, get a response and update the GUI
class MainUIClass(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__()
self.setupUi(self)
self.threadclass = ThreadClass()
self.threadclass.start()
self.threadclass.updateTable.connect(self.updateTable)
self.threadclass2 = ThreadClass2()
self.threadclass2.start()
self.threadclass2.etc.connect(self.etc)
def updateTable(self, val):
#print("update self.table stuff")
def etc(self, val):
#print("update other stuff on gui")
#my first thread. If i have network calls that block i use several threads
class ThreadClass(QtCore.QThread, SharedVars):
updateTable = pyqtSignal(list)
def __init__(self, parent=None):
super().__init__()
def run(self):
def getData():
...
return [data]
while True:
self.updateTable.emit(getData())
#my second thread
class ThreadClass2(QtCore.QThread, SharedVars):
etc = pyqtSignal(list)
def __init__(self, parent=None):
super().__init__()
def run(self):
def getData():
...
return [data]
while True:
self.etc.emit(getData())
if __name__ == "__main__":
a = QtWidgets.QApplication(sys.argv)
app = MainUIClass()
app.show()
sys.exit(a.exec_())
Perhaps there is a better way. Perhaps i can send a signal directly from GUI object to threadclass for example.
Edit: Ok, so "three_pineapples" showed me an example which i converted to qt5, changed some terminology and otherwise changed a bit. I removed the decorators too because i couldnt get them to work with qt5, i don't know if this was a bad idea(although it still seems to work):
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import pyqtSignal, QThread, QTimer
import time
import sys
class MyTask(QtCore.QObject):
disableBtn = pyqtSignal()
enableBtn = pyqtSignal()
def firstTask(self):
self.disableBtn.emit()
print('oooh so much processing...')
time.sleep(4)
print('phew, finished!')
self.enableBtn.emit()
class Window(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__()
self.initUi()
self.setupThread()
def initUi(self):
layout = QtWidgets.QVBoxLayout()
self.button = QtWidgets.QPushButton('Click Me')
layout.addWidget(self.button)
self.setLayout(layout)
self.show()
def enableBtn(self):
self.button.setEnabled(True)
def disableBtn(self):
self.button.setEnabled(False)
def setupThread(self):
self.thread = QThread()
self.task = MyTask()
self.task.moveToThread(self.thread)
#self.thread.started.connect(self.task.firstTask)
self.button.clicked.connect(self.task.firstTask)
self.task.disableBtn.connect(self.disableBtn)
self.task.enableBtn.connect(self.enableBtn)
# Start thread
self.thread.start()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Window()
app.exec_()
Someone talked something about memory problems in the link you posted. I will be frequently updating 3 table elements from DB, is this something i need to be worried about? Also, the usage of time.sleep(). I hear one is not supposed to use time.sleep() with threading? Maybe i can use QThread.msleep instead?