刷新输出定向到PyQt中的QTextEdit

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (1)
  • 查看 (2864)

我有一个PyQt GUI,其中包含一个QTextEdit在代码执行期间显示print语句的框。我选择通过重定向来执行此操作sys.stdout,按照以下这样的帖子:

将python控制台输出打印到Qtextedit

它非常适合记录打印语句,以便用户可以看到执行过程中发生的事情,但是我希望在代码运行时更新它,而不是写入缓冲区并在最后打印出所有内容。例如,在此代码中,单击“运行”按钮将等待5秒钟以打印“正在运行...”和“完成”。函数运行后,我希望它显示'Running ...',等待5秒,然后显示'Done'。

以下是我编写的代码的基础知识:

import sys
import time
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication, QTextEdit
from PyQt5 import QtCore, QtGui


class Stream(QtCore.QObject):
    """Redirects console output to text widget."""
    newText = QtCore.pyqtSignal(str)

    def write(self, text):
        self.newText.emit(str(text))


class GenMast(QMainWindow):
    """Main application window."""
    def __init__(self):
        super().__init__()

        self.initUI()

        # Custom output stream.
        sys.stdout = Stream(newText=self.onUpdateText)

    def onUpdateText(self, text):
        """Write console output to text widget."""
        cursor = self.process.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertText(text)
        self.process.setTextCursor(cursor)
        self.process.ensureCursorVisible()

    def closeEvent(self, event):
        """Shuts down application on close."""
        # Return stdout to defaults.
        sys.stdout = sys.__stdout__
        super().closeEvent(event)

    def initUI(self):
        """Creates UI window on launch."""
        # Button for generating the master list.
        btnGenMast = QPushButton('Run', self)
        btnGenMast.move(450, 100)
        btnGenMast.resize(100, 100)
        btnGenMast.clicked.connect(self.genMastClicked)

        # Create the text output widget.
        self.process = QTextEdit(self, readOnly=True)
        self.process.ensureCursorVisible()
        self.process.setLineWrapColumnOrWidth(500)
        self.process.setLineWrapMode(QTextEdit.FixedPixelWidth)
        self.process.setFixedWidth(400)
        self.process.setFixedHeight(150)
        self.process.move(30, 100)

        # Set window size and title, then show the window.
        self.setGeometry(300, 300, 600, 300)
        self.setWindowTitle('Generate Master')
        self.show()

    def genMastClicked(self):
        """Runs the main function."""
        print('Running...')
        time.sleep(5)
        print('Done.')


if __name__ == '__main__':
    # Run the application.
    app = QApplication(sys.argv)
    app.aboutToQuit.connect(app.deleteLater)
    gui = GenMast()
    sys.exit(app.exec_())

我首先尝试flush=True在print语句中进行设置。但是,我遇到了错误'Stream' object has no attribute 'flush',所以我继续在我创建flushStream类中定义,如下所示:

class Stream(QtCore.QObject):
    """Redirects console output to text widget."""
    newText = QtCore.pyqtSignal(str)

    def write(self, text):
        self.newText.emit(str(text))

    def flush(self):
        sys.stdout.flush()

哪个产生了错误RecursionError:超出了最大递归深度。 这是我的理解用完的地方,因为我已经尝试了其他方法来刷新打印缓冲区,但它们似乎都有这个问题。 关于我做错的任何建议?

提问于
用户回答回答于

这种情况下的问题与flush相关,但是使用了time.sleep()。 time.sleep()是一个阻塞任务,不允许Qt事件循环运行,从而阻止信号正常工作和GUI更新,解决方案是使用QTimer和QEventLoop替换该GUI睡眠。

def genMastClicked(self):
    """Runs the main function."""
    print('Running...')
    loop = QEventLoop()
    QTimer.singleShot(5000, loop.quit)
    loop.exec_()
    print('Done.')

完整代码:

import sys
import time
from PyQt5.QtCore import QObject, pyqtSignal, QEventLoop, QTimer
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication, QTextEdit
from PyQt5.QtGui import QTextCursor


class Stream(QObject):
    """Redirects console output to text widget."""
    newText = pyqtSignal(str)

    def write(self, text):
        self.newText.emit(str(text))


class GenMast(QMainWindow):
    """Main application window."""
    def __init__(self):
        super().__init__()

        self.initUI()

        # Custom output stream.
        sys.stdout = Stream(newText=self.onUpdateText)

    def onUpdateText(self, text):
        """Write console output to text widget."""
        cursor = self.process.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.process.setTextCursor(cursor)
        self.process.ensureCursorVisible()

    def closeEvent(self, event):
        """Shuts down application on close."""
        # Return stdout to defaults.
        sys.stdout = sys.__stdout__
        super().closeEvent(event)

    def initUI(self):
        """Creates UI window on launch."""
        # Button for generating the master list.
        btnGenMast = QPushButton('Run', self)
        btnGenMast.move(450, 100)
        btnGenMast.resize(100, 100)
        btnGenMast.clicked.connect(self.genMastClicked)

        # Create the text output widget.
        self.process = QTextEdit(self, readOnly=True)
        self.process.ensureCursorVisible()
        self.process.setLineWrapColumnOrWidth(500)
        self.process.setLineWrapMode(QTextEdit.FixedPixelWidth)
        self.process.setFixedWidth(400)
        self.process.setFixedHeight(150)
        self.process.move(30, 100)

        # Set window size and title, then show the window.
        self.setGeometry(300, 300, 600, 300)
        self.setWindowTitle('Generate Master')
        self.show()

    def genMastClicked(self):
        """Runs the main function."""
        print('Running...')
        loop = QEventLoop()
        QTimer.singleShot(5000, loop.quit)
        loop.exec_()
        print('Done.')


if __name__ == '__main__':
    # Run the application.
    app = QApplication(sys.argv)
    app.aboutToQuit.connect(app.deleteLater)
    gui = GenMast()
    sys.exit(app.exec_())

热门问答

TSF微服务无法查看JVM监控,显示空白?

工口Miku说唱歌手
推荐
回答来自于问答智囊团成员:邓愉悦 专栏:https://cloud.tencent.com/developer/user/6835587 原因分析 1、tsf-agent 版本过低。 使用 JVM 监控功能时,实例的 tsf-agent 需为 1.21.0 ...... 展开详请

直播推流失败,什么原因导致的呢?

青蛙克星哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
推荐
回答来自于问答智囊团成员:clairehou 专栏:https://cloud.tencent.com/developer/column/89786 经常会收到客户咨询,直播推流失败是什么原因导致。从云直播使用步骤上来讲,直播推流作为第一步,如果推流失败,后续的转码、录制、播放等...... 展开详请

视频播着播着就卡住了,什么原因造成的呢?

推荐
回答来自于问答智囊团成员:bellchen 专栏:https://cloud.tencent.com/developer/article/1734074 猜想 导致视频播放卡顿的原因有千千万万,常见的有如下: 1、网络较差,导致视频下载较慢,需要缓冲,因此卡住了; 可以下载文件到...... 展开详请

云通信图片语音消息发送失败,错误码70402?

宅女have fun……
推荐
回答来自于问答智囊团成员:linpeiyang@云通信 专栏:https://cloud.tencent.com/developer/article/1750251 客户提到文字信息没有失败,说明消息上行到云通信IM后台 -> 云通信IM后台处理 -> 云通信IM后台下发消息给用...... 展开详请

即时通信如何像QQ一样实现加好友、备注、进行好友分组?

五星格兰特就事论事不撕逼!三观不合删评价!
推荐
回答来自于问答智囊团成员:linpeiyang@云通信 专栏:https://cloud.tencent.com/developer/article/1750251 即时通信IM默认有2种关系链 好友 黑名单 均可以通过以下两种方式实现增删改查的功能: 调用REST API 调用...... 展开详请

CPU负载100%,但并看不到具体哪个进程导致的,?

鸿鹄认真生活 做出美好的产品 App/VR/美国市场
推荐
回答来自于问答智囊团成员:何刚 专栏:https://cloud.tencent.com/developer/user/6827370 安全分析 1、隐藏进程 经过busybox核实到存在隐藏进程,百度核实为挖矿病毒 📷 2、crontab 存在异常任务 📷 下载链接已经失效,I...... 展开详请

所属标签

扫码关注云+社区

领取腾讯云代金券