这可能是非常基本的,但它让我头疼,而且我不确定采用什么方法,使谷歌搜索变得困难。
如果我在一个模块中有一个类,我要导入各种打印件,我怎样才能读取打印件,以便将它们输出到PyQT文本标签?
class Worker(QtCore.QThread, object):
class statusWrapper(object):
def __init__(self, outwidget):
self.widget = outwidget
def write(self, s):
self.widget.setText(s)
def __init__(self, widget):
QtCore.QThread.__init__(self)
sys.stdout = statusWrapper(widget)
def run(self):
self.runModule() #This is the module with the prints within.
当runModule被执行时,一些神秘的东西被传递给statusWrapper.write,但它是空白的。我究竟做错了什么?
感谢。
答案 0 :(得分:1)
您可以将StringIO对象用作stdout,而不是编写自己的statusWrapper类。类似的东西:
def __init__(self, widget):
QtCore.QThread.__init__(self)
def run(self):
real_stdout = sys.stdout
sys.stdout = StringIO.StringIO()
self.runModule()
label_text = sys.stdout.getvalue()
sys.stdout = real_stdout
恢复标准输出的原始值对您的理智很重要。另请注意,这在多线程环境中无法达到预期效果。另请注意,delnan当然是正确的,替换stdout是一种令人难以置信的hackish方式。
如果你想要的东西会在每次模块打印输出时更新标签(有点像穷人的状态指示器),那么有更好的方法可以做到这一点 - 你可以用回调函数调用替换打印件,您在导入模块时在模块中设置的,或类似的东西。
答案 1 :(得分:1)
神秘的东西传递给了 runModule时的statusWrapper.write 被执行,但它是空白的。是什么 我做错了吗?
这并不神秘:write
只接收写入sys.stdout
的每个字符串(在这种情况下,就是你的包装器)。
错误可能是包装器仅调用setText
,在每次写入时替换小部件的文本,而不是附加到它。你至少需要做一些事情:
def write(self, s):
self.widget.setText(self.widget.text() + s)
(或者更有效的方法是将文本附加到QT小部件)。
重定向sys.stdout
的更好方法是使用上下文管理器。 PEP 343定义了以下示例:
from contextlib import contextmanager
@contextmanager
def stdout_redirected(new_stdout):
save_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout = save_stdout
您可以使用它:
class Worker(QtCore.QThread, object):
def run(self):
with stdout_redirected(StatusWrapper(widget)):
self.runModule()
除了更具可读性之外,如果runModule
引发异常(这对你的理智很重要: - ),这个上下文管理器确保恢复sys.stdout。
答案 2 :(得分:0)
最简单(仍然错误 - 正确的方法是更改函数)方式是将stdout重定向到标签(print写入sys.stdout)。有关QPlainTextEdit的简单示例,请参阅Wxwidgets and Pyqt,应该很容易针对QLabel进行调整。