【问题标题】:PySide: redirect stdout to a dialogPySide:将标准输出重定向到对话框
【发布时间】:2015-03-07 14:38:21
【问题描述】:

我有一个 pyside 应用程序,它在 QThread 中运行一个函数。这个函数经常使用print。如何将标准输出重定向到一个对话框(包含 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

但这只会导致我的应用程序冻结。

有什么想法吗?

【问题讨论】:

  • 我很惊讶您无法让“将 stdout 和 stderr 从辅助线程重定向到 PyQt4 QTextEdit”中的方法工作。我在答案中提供的示例代码仍然为我运行。无论如何,希望我对这个问题的回答可以解决您当前方法的问题。

标签: python python-2.7 pyqt stdout pyside


【解决方案1】:

堆栈溢出答案解释了您的打印行仅在工作人员完成后才显示的原因:https://stackoverflow.com/a/20818401/1994235

总而言之,在处理跨线程的信号/槽时,您需要用@pyqtslot(types) 装饰槽,以确保它们实际上在您想要的线程中运行。

【讨论】:

    【解决方案2】:

    这似乎可以通过子类化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)
    

    但是,网络上的大多数文档似乎都建议您不要将 QThread 子类化,而是使用 moveToThread 函数来处理任务。

    另外,我不知道你在上面的方法中如何区分stdoutstderr(假设你都重定向到工作线程)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-26
      • 2016-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多