I'm making a light GUI program with PyQT5.
But now I'm facing some problem about thread.
I just made simple test program like bottom:
the program simply trying to append numbers to textbox, but it crashes.
I don't know why but somehow I can prevent it by removing a comment(time.sleep)
import sys
import threading
import time
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class Some(QWidget):
e = threading.Event()
def btnfunc(self):
self.e.set()
def __init__(self):
super().__init__()
self.myButton = QPushButton('do next')
self.logs = QTextEdit()
self.mylay = QVBoxLayout()
self.mylay.addWidget(self.myButton)
self.mylay.addWidget(self.logs)
self.setLayout(self.mylay)
self.setGeometry(300, 300, 300, 550)
self.setWindowTitle('mytest')
self.show()
t = threading.Thread(target=self.myfunc, args=( ))
t.start()
self.myButton.clicked.connect(self.btnfunc)
def myfunc(self):
for i in range(300):
# time.sleep(0.4)
self.logs.append(str(i))
if i == 20:
self.e.wait()
app = QApplication(sys.argv)
ex = Some()
sys.exit(app.exec_())
It would be better if sets time higher.
I thought it is because of resource accessing, since it is pyQT5 GUI.
So I've find QThread. and I tried like bottom,
import sys
import time
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class Some(QWidget):
qw = QWaitCondition()
qm = QMutex()
def btnfunc(self):
self.qw.wakeAll()
def __init__(self):
super().__init__()
self.myButton = QPushButton('do next')
self.logs = QTextEdit()
self.mylay = QVBoxLayout()
self.mylay.addWidget(self.myButton)
self.mylay.addWidget(self.logs)
self.setLayout(self.mylay)
self.setGeometry(300, 300, 300, 550)
self.setWindowTitle('mytest')
self.show()
self.myButton.clicked.connect(self.btnfunc)
self.thread = QThread()
self.thread.started.connect(self.myfunc)
self.thread.start()
def myfunc(self):
for i in range(300):
self.logs.append(str(i))
if i == 20:
self.qw.wait(self.qm)
app = QApplication(sys.argv)
ex = Some()
sys.exit(app.exec_())
But crashes, doesn't work. and tried QThread+threading.Event(). It freezes GUI.
Now I don't know how to proceed it...
Edit: I just realized about thread. Should not be accessed from other thread except QThread. Then I will keep find about QWaitCondition
You should not control GUI directly via multithreading. Since two different threads are trying to control the GUI this results to freeze or crash. I have learnt about this concept from here http://www.xyzlang.com/python/PyQT5/pyqt_multithreading.html
Here is your code that will work perfectly.
import sys
import threading
import time
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
# Added new
class Communicate(QObject):
signal = pyqtSignal(str)
class Some(QWidget):
e = threading.Event()
def btnfunc(self):
self.e.set()
def __init__(self):
super().__init__()
#communicate object
self.comm = Communicate()
self.comm.signal.connect(self.append_data)
self.myButton = QPushButton('do next')
self.logs = QTextEdit()
self.mylay = QVBoxLayout()
self.mylay.addWidget(self.myButton)
self.mylay.addWidget(self.logs)
self.setLayout(self.mylay)
self.setGeometry(300, 300, 300, 550)
self.setWindowTitle('mytest')
self.show()
t = threading.Thread(target=self.myfunc, args=( ))
t.start()
self.myButton.clicked.connect(self.btnfunc)
def myfunc(self):
for i in range(300):
# time.sleep(0.4)
#self.logs.append(str(i))
self.comm.signal.emit(str(i))
if i == 20:
self.e.wait()
def append_data(self, data):
self.logs.append(data)
app = QApplication(sys.argv)
ex = Some()
sys.exit(app.exec_())