self.trigger.connect(Output().main())
This line is problematic. You create a class in a stream that looks like a widget. This is not true. You should not use GUI elements in another thread. All GUI-related code must run in the same thread with the event loop.
The above line is also incorrect in terms of design. You emit a custom signal from your stream, and this is a good way. But the object for processing this signal should be the one that owns / creates the stream, namely yourMainWindow
. , . , , , .
:
import sys
from PyQt4 import QtGui, QtCore
import time
import random
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
def setup(self, thread_no):
self.thread_no = thread_no
def run(self):
time.sleep(random.random()*5)
self.trigger.emit(self.thread_no)
class Main(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.text_area = QtGui.QTextBrowser()
self.thread_button = QtGui.QPushButton('Start threads')
self.thread_button.clicked.connect(self.start_threads)
central_widget = QtGui.QWidget()
central_layout = QtGui.QHBoxLayout()
central_layout.addWidget(self.text_area)
central_layout.addWidget(self.thread_button)
central_widget.setLayout(central_layout)
self.setCentralWidget(central_widget)
def start_threads(self):
self.threads = []
for i in range(10):
thread = MyThread(self)
thread.trigger.connect(self.update_text)
thread.setup(i)
thread.start()
self.threads.append(thread)
def update_text(self, thread_no):
self.text_area.append('thread # %d finished' % thread_no)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainwindow = Main()
mainwindow.show()
sys.exit(app.exec_())