如何在不影响其他事件的情况下实时更新文本(pyqt)

时间:2016-03-06 10:11:30

标签: python multithreading qt pyqt

在我的程序中,我想不断将文本设置为文本浏览器,但是当我点击另一个按钮时似乎有延迟。有我的代码:

class Ui_MainWindow(QWidget):
  def __init__(self):
    QWidget.__init__(self)
    self.setupUi(self)
    self.th0 = TestThread()
    self.pushButton.clicked.connect(self.runthread)

  def runthread(self):
    self.th0.start()
    self.chilWid.Consumer()
    QtGui.qApp.processEvents()

  def setupUi(self, Widget):             
    self.gridLayout = QtGui.QGridLayout()
    self.pushButton = QtGui.QPushButton()
    self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
    self.chilWid = ChildWid()
    self.gridLayout.addWidget(self.chilWid, 1, 0, 1, 1)

    self.setLayout(self.gridLayout)

manager = Manager()
manager2 = Manager()
q = manager.Queue()
q2 =manager2.Queue()
l = manager.Lock()
l2 =manager2.Lock()

这个类是一个控制生产者的线程

class TestThread(QThread):
 def __init__(self):
    QThread.__init__(self)
    self.t = ChildWid()
 def run(self):
    while (not self.stopped):
        ps0 = Process(target=Producer, args=(q, l, 'eth0', q2, l2))        
        #### Producer is another program that will generate 
             text continually and save into q
        ps0.start()    

此类只包含一个文本浏览器,将由MainWindow类插入。它还从队列中收集数据并将其显示在文本浏览器

class ChildWid(QWidget):
 def __init__(self):
    QWidget.__init__(self)
    self.text = QTextEdit()
    self.lay = QHBoxLayout(self)
    self.lay.addWidget(self.text)

 def Consumer(self):
    global q, q2, q3,l,l2,l3
    while True:
        try:
            task = q.get(block=False)
            QtGui.qApp.processEvents()
            self.text.setText(str(task))
        except:
            pass

当我点击pushButton时,文字浏览器会正常显示由Producer生成的文字。但是像pushbutton这样的另一个按钮或整个用户界面响应非常慢。给我任何建议吗?感谢

**********新更新

class TestThread(QThread,QObject):
testsinal = pyqtSignal(str)

def __init__(self):
     . . .
    self.t = ChildWid()

def TestSignal(self):
    self.testsinal.emit('some text message')
    self.testsinal.connect(self.handle)
@QtCore.pyqtSlot(str)
def handle(self,str):
    print str
    self.t.text.setText(str)

def run(self):
    print"Thread run normally"
    while (self.stopped):
        ps0 = Process(target=L2PS_v1a4.main, args=(q, l, 'eth0', q2, l2, q3))
        ps0.start()

        self.TestSignal()

1 个答案:

答案 0 :(得分:1)

带有阻塞Consumer循环的while方法看起来非常讨厌。它试图像某种虚假的事件循环,但它没有办法像真实的东西一样有效地运作。摆脱它。

执行此操作的正确方法是在TestThread类上定义自定义信号,然后使用它从run()方法中发出文本消息。跨线程信号是线程安全的,并发布到接收线程的事件队列中。这意味着它们是异步处理的,因此不会阻止GUI:

class TestThread(QThread):
    testSignal = QtCore.pyqtSignal(str)
    ...

    def run(self):
        while (not self.stopped):
            ps0 = Process(target=Producer, args=(q, l, 'eth0', q2, l2))        
            ps0.start()
            self.testSignal.emit('some text message')


class ChildWid(QWidget):
    ...

    QtCore.pyqtSlot(str)
    def handleTestSignal(self, message):
        print(message)
        self.text.setText(message)


class Ui_MainWindow(QWidget):
    def __init__(self):
        ...
        self.th0.testSignal.connect(self.chilWid.handleTestSignal)