简体   繁体   English

如何在pyQt4中的不同线程中清除QTextEdit

[英]how to clear QTextEdit in different thread in pyQt4

I have a QTextEdit component created in the "main" thread of my program then I start another thread, which will be updating this QTextEdit every x seconds, but then I get this error: 我有一个QTextEdit组件在我的程序的“主”线程中创建然后我启动另一个线程,它将每隔x秒更新此QTextEdit,但后来我得到此错误:

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

this is the way I'm doing it: 这就是我这样做的方式:

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

this two last lines of code give me the above mentioned error. 这最后两行代码给出了上面提到的错误。 Can someone give me a clue on how to handle this? 有人能给我一个如何处理这个问题的线索吗?

thanks! 谢谢!

One of the main gotcha's about Qt is that you cannot call any QWidget methods from any thread other than the main GUI thread. 关于Qt的一个主要问题是你不能从主GUI线程以外的任何线程调用任何QWidget方法。 All of your communication must be done by emitting signals from the extra threads, which will forward to the main gui. 所有的通信都必须通过从额外线程发出信号来完成,这些信号将转发到主gui。

To start, I see you are using globals, and a lack of the self keyword, so I assume you are not using classes. 首先,我看到你正在使用全局变量,并且缺少self关键字,所以我假设你没有使用类。 My example will incorporate a class example as well. 我的例子也将包含一个类示例。

This is example is bare bones, just like yours, outlining the direction you might want to take: 这个例子很简单,就像你的一样,概述了你可能想要的方向:

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)

The main thing to notice is that the functions running in the thread are emitting signals. 需要注意的主要是线程中运行的函数是发出信号。 They have no knowledge of the QWidgets in the other classes. 他们不了解其他课程中的QWidgets。 Your MyWidget class connects the signal to a slot that can update the QLineEdit. 您的MyWidget类将信号连接到可以更新QLineEdit的插槽。 When the thread emits a signal, it will be queued into the main thread and executed by the receiving slot. 当线程发出信号时,它将排队到主线程并由接收槽执行。

I also created a simple QThread subclass that can take a function and args, replicating the way the standard lib Thread class works. 我还创建了一个简单的QThread子类,它可以接受一个函数和args,复制标准的lib Thread类的工作方式。 You should stick to using QThread because it is a QObject subclass, and supports signals and can run an event loop. 您应该坚持使用QThread,因为它是一个QObject子类,并且支持信号并且可以运行事件循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM