【问题标题】:Display terminal output with tqdm in QPlainTextEdit在 QPlainTextEdit 中使用 tqdm 显示终端输出
【发布时间】:2019-04-22 05:54:40
【问题描述】:

我正在尝试找到一种方法来获取 pyqt 应用程序中进度条的结果/演变以及其他打印,例如在 QPlainTextEdit 小部件中。

我面临的问题是,进度条可以使用一些更高级的回车,甚至更高级的光标定位,这些大多不被 treams 支持。 我试过io.StringIO,但\r 保持原样。

import io
from tqdm import tqdm
s = io.StringIO()
for i in tqdm(range(3), file=s):    
    sleep(.1)

输出:

s.getvalue()

Out[24]: '\n\r  0%|          | 0/3 [00:00<?, ?it/s]\x1b[A\n\r 33%|###3      | 1/3 [00:00<00:00,  9.99it/s]\x1b[A\n\r 67%|######6   | 2/3 [00:00<00:00,  9.98it/s]\x1b[A\n\r100%|##########| 3/3 [00:00<00:00,  9.98it/s]\x1b[A\n\x1b[A'

翻译成:

print(s.getvalue())
  0%|          | 0/3 [00:00<?, ?it/s]
 33%|###3      | 1/3 [00:00<00:00,  9.99it/s]
 67%|######6   | 2/3 [00:00<00:00,  9.98it/s]
100%|##########| 3/3 [00:00<00:00,  9.98it/s]

明确地说,在我的输出中,我不希望每次 tqdm 更新一行,而只希望当前状态,因为它将打印在命令行上。

知道怎么做吗? 谢谢!

【问题讨论】:

  • 什么是text widget
  • 任何显示多行文本的小部件,例如 QPlainTextEdit
  • 是的,当然,那是为了演示。
  • 感谢您的帮助!我想要的内容与我在标准输出中看到的内容基本相同,但在一个字符串中,或​​者我可以在 qt 小部件中显示的任何内容。

标签: python pyqt pyqt5 tqdm qplaintextedit


【解决方案1】:

如果添加了新文本,想法是删除前一行,但您还必须删除 \r 并验证它不是空文本。另外,一个对象要接收tqdm的文本,它必须只有write()方法,所以实现一个自定义的QPlainTextEdit。使用QMetaObject::invokeMethod() 使其成为线程安全的

import time
import threading
from tqdm import tqdm
from PyQt5 import QtCore, QtGui, QtWidgets
import lorem

class LogTextEdit(QtWidgets.QPlainTextEdit):
    def write(self, message):
        if not hasattr(self, "flag"):
            self.flag = False
        message = message.replace('\r', '').rstrip()
        if message:
            method = "replace_last_line" if self.flag else "appendPlainText"
            QtCore.QMetaObject.invokeMethod(self,
                method,
                QtCore.Qt.QueuedConnection, 
                QtCore.Q_ARG(str, message))
            self.flag = True
        else:
            self.flag = False

    @QtCore.pyqtSlot(str)
    def replace_last_line(self, text):
        cursor = self.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.select(QtGui.QTextCursor.BlockUnderCursor)
        cursor.removeSelectedText()
        cursor.insertBlock()
        self.setTextCursor(cursor)
        self.insertPlainText(text)

def foo(w):
    for i in tqdm(range(100), file=w):
        time.sleep(0.1)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = LogTextEdit(readOnly=True)
    w.appendPlainText(lorem.paragraph())
    w.appendHtml("Welcome to Stack Overflow")
    w.show()
    threading.Thread(target=foo, args=(w,), daemon=True).start()
    sys.exit(app.exec_())

【讨论】:

  • 谢谢,我需要一点时间来测试它是否符合我的需要,但请确保我会在它工作后立即接受
猜你喜欢
  • 2020-09-11
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-06
  • 2012-11-15
  • 2012-07-30
  • 1970-01-01
相关资源
最近更新 更多