我有一个pyside应用程序,它在QThread中运行一个函数。此功能通常使用print
。如何将stdout重定向到对话框(包含qtextedit
或类似对话框),该对话框将在函数运行时显示。
这是一个最小的例子:
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)
我可以修改worker以将stdout重定向到自身,然后将文本作为信号发出:
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)
但是当我将此信号连接到OutputDialog
实例时,只有在工作人员完成后才显示文本。
我也试过在这里实现这个方法: Redirecting stdout and stderr to a PyQt4 QTextEdit from a secondary thread
但它只会导致我的应用冻结。
有什么想法吗?
答案 0 :(得分:1)
这个堆栈溢出答案解释了一旦工人完成后打印行只显示的原因:https://stackoverflow.com/a/20818401/1994235
总而言之,在处理跨线程的信号/插槽时,需要使用@pyqtslot(types)
来装饰插槽,以确保它们实际上在您想要的线程中运行。
答案 1 :(得分:0)
似乎可以通过继承QThread
:
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 thread and run it
self.thread = WorkerThread()
self.thread.message.connect(self.viewer.write)
self.thread.start()
class WorkerThread(QtCore.QThread):
message = QtCore.Signal(str)
def run(self):
sys.stdout = self
for i in range(10):
print "Im doing stuff"
time.sleep(1)
def write(self, text):
self.message.emit(text)
但是,Web上的大多数文档似乎都建议您不要将QThread子类化,而是使用moveToThread
函数来处理任务。
另外,我不知道如何在上述方法中区分stdout
和stderr
(假设您将两者都重定向到了workerthread)