【问题标题】:how to clear QTextEdit in different thread in pyQt4如何在pyQt4的不同线程中清除QTextEdit
【发布时间】:2012-08-28 05:21:41
【问题描述】:

我在程序的“主”线程中创建了一个 QTextEdit 组件 然后我启动另一个线程,它将每 x 秒更新一次此 QTextEdit,但随后我收到此错误:

QObject: Cannot create children for a parent that is in a different thread.

这就是我的做法:

def initGui():
   #some gui components
   global txt_list

   txt_list = QtGui.QTextEdit(w)
   txt_list.resize(580,400)
   txt_list.move(50, 50)
   txt_list.setReadOnly(1)
   txt_list.setFont(font_consolas)
   #more gui components

def update_list():
   t_monitor = threading.Thread(target=monitor_vector)
   t_monitor.daemon = True
   t_monitor.setName('monitor')
   t_monitor.start()

def monitor_vector():
   #retrieve info...
   lock = threading.Lock
   lock = True
   txt_list.clear() #clear list, to set the new one
   txt_list.setText('updated list')
   lock = False

最后两行代码给了我上面提到的错误。有人可以告诉我如何处理这个问题吗?

谢谢!

【问题讨论】:

    标签: python multithreading pyqt4


    【解决方案1】:

    关于 Qt 的主要问题之一是您不能从除主 GUI 线程之外的任何线程调用任何 QWidget 方法。您的所有通信都必须通过从额外线程发出信号来完成,这些信号将转发到主 gui。

    首先,我看到您使用的是全局变量,并且缺少 self 关键字,所以我假设您没有使用类。我的示例也将包含一个类示例。

    这是一个简单的例子,就像你的一样,概述了你可能想要采取的方向:

    from PyQt4 import QtGui, QtCore
    
    class MyWidget(QtGui.QWidget):
    
        def __init__(self, parent=None):
            super(MyWidget, self).__init__(parent)
    
            ...
            self.txt_list = QtGui.QTextEdit(self)
            self.txt_list.resize(580,400)
            self.txt_list.move(50, 50)
            self.txt_list.setReadOnly(1)
            self.txt_list.setFont(font_consolas)
            ...
            self.monitor = Monitor()
            self.monitor.updateText.connect(self._handleTextUpdate)
            self.monitor.update_list()
    
        def _handleTextUpdate(self, txt):
            self.txt_list.clear()
            self.txt_list.setText(txt)
    
    
    class Monitor(QtCore.QObject):
    
        updateText = QtCore.pyqtSignal(str)
    
        def update_list(self):
            t_monitor = Thread(self.monitor_vector, parent=self)
            t_monitor.daemon = True
            t_monitor.setName('monitor')
            t_monitor.start()
    
        def monitor_vector(self):
            ...
            self.updateText.emit('updated list')
    
    
    class Thread(QtCore.QThread):
    
        def __init__(self, fn, args, kwargs, parent=None):
            super(Thread, self).__init__(parent)
            self._fn = fn 
            self._args = args 
            self._kwargs = kwargs 
    
        def run(self):
            self._fn(*self._args, **self._kwargs)
    

    主要需要注意的是线程中运行的函数正在发出信号。他们不了解其他类中的 QWidget。您的 MyWidget 类将信号连接到可以更新 QLineEdit 的插槽。当线程发出信号时,它会被排入主线程并由接收槽执行。

    我还创建了一个简单的 QThread 子类,它可以采用函数和参数,复制标准 lib Thread 类的工作方式。您应该坚持使用 QThread,因为它是 QObject 的子类,并且支持信号并且可以运行事件循环。

    【讨论】:

    • 我是这样做的,得到:TypeError: pyqtSignal must be bound to a QObject, not 'instance'
    • 你确定把它作为一个类属性并且 NOT 在你的__init__ 中吗?
    • 是的,最后我发现了我的错误,我在主类中声明了信号......它现在就像一个魅力,非常感谢你必须提供帮助的朋友!
    猜你喜欢
    • 2018-08-17
    • 1970-01-01
    • 1970-01-01
    • 2014-01-31
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    相关资源
    最近更新 更多