如何在gui打开时使用线程来更新PyQt中的文本字段?

时间:2015-10-27 18:30:54

标签: python multithreading user-interface pyqt4

我在PyQt GUI上有一个文本字段,用于从另一个文件打印文本,但是该文件可能会经常更改,因此我希望textfield每10秒更新一次,以便用户可以看到实时文件文本。 这是我正在使用的淡化版本,但是线程不起作用:/tmp/py.state.test文件写得太连续,所以我希望这个更改出现在QTextBrowser上。就像现在一样,如果我运行该程序,它将正确地初始化文本,但它在运行时不会更新。

from PyQt4 import QtGui, QtCore
from PyQt4.Qt import *
import sys, os, threading, time

class TestWindow(Qt.Gui.QWidget):

    def __init__(self):
        super(TASwitchWindow, self).__init__()
        self.initUI()

    def initUI(self):
        t=threading.Thread(target.self.cfglabel())
        t.start()
        t.join()
        self.setGeometry(200,200,800,600)
        self.setWindowTitle('TA Switch Tab')
        self.show()

    def cfglabel(self):
        self.lbl = QtGui.QTextBrowser(self)
        self.lbl.resize(760,40)
        self.lbl.move(20,440)
        with open ("/tmp/py.state.test", "r") as myfile:
            data=myfile.read().replace('\n', '')
        self.lbl.append(data)
        time.sleep(10)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    win = TestWindow()
    sys.exit(app.exec_())

道歉,可能存在拼写错误,因为我的代码在另一个系统上,我不得不重新输入它。如果有人能告诉我如何每10秒更新一次文本,那就太棒了。使用QLabel或其他内容而不是TextBrowser会更好吗?感谢

2 个答案:

答案 0 :(得分:1)

听起来你真的想要实现一个计时器。 QTimers非常易于使用。

@"Unilateral pulmonary emphysema [MacLeod's syndrome]"

答案 1 :(得分:1)

您的代码存在一些问题,导致其无法正常工作。

  1. 您正在从线程更新GUI。这在Qt中是禁止的。必须从主线程完成与GUI对象的所有交互,否则您的程序将随机崩溃。您需要使用QThread并从QThread向主线程中的一个插槽发出信号,然后与GUI对象进行交互(信号发射是线程安全的,几乎所有其他都不是)

  2. 当您实例化Python线程时,您没有传递对要在线程中运行的方法的引用。你写过t=threading.Thread(target.self.cfglabel())。请注意cfglabel之后的额外括号。你实际做的是在主线程中运行cfglabel方法,并使用它的返回值(在你的情况下为None)作为应该在线程中运行的方法。显然这不起作用!代码行应改为t=threading.Thread(target.self.cfglabel)

  3. 等待线程在应用程序开始运行之前完成(t.join())。所以当然线程永远不会在后台运行以不断更新GUI。您不想在用例中加入该主题。

  4. 上面提到的#3中的更改要求您保存对线程的引用,以便在initUI方法完成运行后不会对其进行垃圾回收。我建议将其存储为实例属性:aka self.t

  5. 重新加载文件的代码不在while循环中。所以目前它只加载文件一次,而不是每10秒重新加载一次。您不希望cfglabel方法永远结束(当它结束时,线程也是如此,您将不再获得更新)。因此,您希望代码变为:

  6. _

    def cfglabel(self):
        self.lbl = QtGui.QTextBrowser(self)
        self.lbl.resize(760,40)
        self.lbl.move(20,440)
    
        while True:
            self.lbl.clear()
            with open ("/tmp/py.state.test", "r") as myfile:
                data=myfile.read().replace('\n', '')
            self.lbl.append(data)
            time.sleep(10)
    

    请注意,上面的代码没有考虑上面第1点中提出的必要修改,并且可能会导致程序崩溃。与self.lbl的所有操作都需要移动到主线程中,您需要使用QThread,以便定义和发出自定义信号。

    希望这有助于未来的线程化工作,但在这种情况下,使用QTimer是最简单的选择,前提是文本文件的读取不会成为瓶颈。