如何将tqdm文本内容流式传输到PySide2 GUI?
我正在使用 jMetalPy。它有一个叫做 "ProgressBarObserver" 的功能,利用 tqdm 来显示计算进度。
https://github.com/jMetal/jMetalPy/blob/main/jmetal/util/observer.py
我有一个基于 PySide2 的图形界面,它可以在界面上显示控制台的内容,令我惊讶的是,除了 tqdm 的内容,其他的都能在界面上显示出来。
class EmittingStream(QtCore.QObject):
textWritten = Signal(str)
def write(self, text):
self.textWritten.emit(text)
def flush(self):
pass
.....
# Console print
self.textBrowser = self.ui.textBrowser_log
# Create a custom stream object for the QTextBrowser.
self.textBrowserStream = EmittingStream()
self.textBrowserStream.textWritten.connect(self.textBrowser.append)
# Redirect output to the QTextBrowser, but not the output from pandas.
sys.stdout = self.textBrowserStream
pd.option_context('display.max_rows', None, 'display.max_columns', None, 'display.expand_frame_repr', False)
我在使用 PyCharm,控制台的打印内容是白色的,但 tqdm 的内容是红色的,显然这些文本是不同的,可能需要用不同的方式来处理。我该如何让这些内容也能出现在我的文本流输出中呢? 为了更清楚地说明,tqdm 的内容在 PyCharm 中显示正常,但在 PySide2 的图形界面中只显示了普通的白色文本打印语句。谢谢!
2 个回答
穆罕默德的回答听起来像是个糟糕的AI回复。
我最后修改了jMetalpy的ProgressBarObserver类,添加打印语句对我来说就足够了。它会在控制台或图形界面上循环打印进度。
class ProgressBarObserver(Observer):
def __init__(self, max: int) -> None:
""" Show a smart progress meter with the number of evaluations and computing time.
:param max: Number of expected iterations.
"""
self.progress_bar = None
self.progress = 0
self._max = max
def update(self, *args, **kwargs):
if not self.progress_bar:
self.progress_bar = tqdm(total=self._max, ascii=True, desc='Progress')
evaluations = kwargs['EVALUATIONS']
self.progress_bar.update(evaluations - self.progress)
self.progress = evaluations
### I added this line here ###
print(f"Evaluations: {evaluations}", file=sys.stdout)**
if self.progress >= self._max:
self.progress_bar.close()
看起来你遇到的问题可能是因为tqdm的输出处理方式和普通的打印语句不一样。tqdm使用一些特殊的控制代码来动态更新进度条,而这些代码在重定向到QTextBrowser时可能无法正确显示。
为了在你的PySide2图形界面中处理tqdm的输出,你需要单独拦截和处理tqdm的输出。一种方法是从jMetalPy的ProgressBarObserver类继承一个新的类,并重写它的on_progress_bar_update方法,这样就可以发出信号来更新tqdm的进度。然后,你可以把这些信号连接到你的图形界面上,以便进行更新。
--- 将tqdm观察者添加到图形界面 ----
tqdm_observer = TqdmProgressBarObserver()
self.textBrowser.add_tqdm_observer(tqdm_observer)