I have a pyside application which runs a function in a QThread. This function often uses print
. How can I redirect the stdout to a dialog (containing a qtextedit
or similar) which will display when the function is run.
Here is a minimal example:
class Main(QtGui.QWindow):
def __init__(self):
super(Main, self).__init__()
self.run_button = QtGui.QPushButton("Run")
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(self.run_button)
self.setLayout(mainLayout)
self.run_button.clicked.connect(self.run_event)
def run_event(self):
# Create the dialog to display output
self.viewer = OutputDialog()
# Create the worker and put it in a thread
self.worker = Worker()
self.thread = QtCore.QThread()
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.run)
self.worker.finished.connect(self.thread.quit)
self.thread.start()
class Worker(QtCore.QObject):
finished = QtCore.Signal()
def run(self):
for i in range(10):
print "Im doing stuff"
time.sleep(1)
self.finished.emit()
class OutputDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(OutputDialog, self).__init__(parent)
self.text_edit = QtGui.QTextEdit()
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(self.text_edit)
self.setLayout(vbox)
I can modify the worker to redirect stdout to itself, and then emit the text as a signal:
class Worker(QtCore.QObject):
finished = QtCore.Signal()
message = QtCore.Signal(str)
def __init__(self):
super(Worker, self).__init__()
sys.stdout = self
def run(self):
for i in range(10):
print "Im doing stuff"
time.sleep(1)
self.finished.emit()
def write(self, text):
self.message.emit(text)
But when I connect this signal to the OutputDialog
instance, the text is only displayed once the worker has finished.
I have also tried implementing the method here: Redirecting stdout and stderr to a PyQt4 QTextEdit from a secondary thread
But it just causes my app to freeze.
Any ideas?