【问题标题】:Updating Python GUI element from Qthread从 Qthread 更新 Python GUI 元素
【发布时间】:2015-05-29 22:37:37
【问题描述】:

所以我知道有很多关于使用 Qthread 更新 GUI 中的元素的帖子。我已尽力复习这些,但仍有一个问题。

我正在尝试创建一个 GUI,该 GUI 在单击按钮时运行一个方法,然后该方法启动一个新线程。然后该线程向 GUI 发出信号以更改 GUI 元素的值:

from PySide import QtCore, QtGui
import time

class WorkerThread(QtCore.QThread):
    updateProgress = QtCore.Signal(int)
    def __init__(self, countto):
        QtCore.QThread.__init__(self)
        self.countto = countto

    def run(self):
        i = 0
        while i <= self.countto:
            print(self.countto)
            self.updateProgress.emit(i)
            time.sleep(1)
            i += 1


class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(400, 300)
        self.progressBar = QtGui.QProgressBar(Dialog)
        self.progressBar.setGeometry(QtCore.QRect(110, 120, 118, 23))
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.lineEdit = QtGui.QLineEdit(Dialog)
        self.lineEdit.setGeometry(QtCore.QRect(50, 60, 113, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.pushButton = QtGui.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(190, 60, 75, 23))
        self.pushButton.setObjectName("pushButton")

        self.wt = WorkerThread(int)
        self.wt.updateProgress.connect(self.setProgress)

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
        self.pushButton.setText(QtGui.QApplication.translate("Dialog", "PushButton", None, QtGui.QApplication.UnicodeUTF8))
        self.pushButton.connect(QtCore.SIGNAL('clicked()'), self.get_time)

    def setProgress(self, progress):
        self.progressBar.setValue(progress)

    def get_time(self):
        countto = self.lineEdit.text()
        countto = int(countto)
        print(countto)
        self.wt = WorkerThread(countto)
        self.wt.start()
        q = 0
        while q < 5:
            print(countto+2)
            time.sleep(2)
            q += 1


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Dialog = QtGui.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())

这个 GUI 应该运行主线程并进行一些任意计数以确保它正常工作。然后第二个线程也进行一些任意计数以确保它正常工作,然后尝试向 GUI 发出信号以更新progressbar 元素。我知道两个线程都在运行,但我认为我在接收信号时遇到了问题,因为progressbar 没有更新。我已经尝试了一些东西,但现在我被卡住了。我认为当我尝试将值传递给线程并且尝试在“setupUi”方法中创建线程的实例时出现问题,只是稍后重新定义它。

谁能帮助解释我的思维错误?我正在尝试使用带有线程的信号和插槽来解决问题,所以解释一下会很好。

【问题讨论】:

    标签: python-2.7 pyqt qthread


    【解决方案1】:

    你的代码有一些问题,但你已经很接近了。

    第一个明显的问题是您的主线程中有一个带有time.sleep() 的循环。 Ui_Dialog.get_time() 方法在主线程中运行(应该如此)。你不应该在那里有任何长时间运行的代码。但是,带有time.sleep(2) 的循环是长时间运行的代码。就目前而言,您的 GUI 被锁定,因为控制它在 2*countto 秒内没有返回到 GUI 事件循环。只需删除整个 while 循环。我真的不知道它为什么在那里。

    删除这个:

    q = 0
    while q < 5:
        print(countto+2)
        time.sleep(2)
        q += 1
    

    下一个问题是因为每次单击按钮时都会重新创建QThread。因此,对于每个新对象,您需要将该对象中的updateProgress 信号连接到setProgress 插槽。所以把那里的代码改成:

    self.wt = WorkerThread(countto)        
    self.wt.updateProgress.connect(self.setProgress)
    self.wt.start()
    

    此时您将看到进度条正确更新。但是,进度条的最大值默认设置为 100。因此,您可能希望在创建线程之前将最大值设置为countto。例如:

    self.progressBar.setMaximum(countto)
    self.wt = WorkerThread(countto)    
    

    希望能解释清楚!

    【讨论】:

    • 啊,谢谢!有效。我只是使用time.sleep 来显示线程正在运行。用它作为我的学习工具。也谢谢你的解释,我真的很感激。我还删除了setup_Ui 方法中定义的self.wt = WorkerThread(int)' and 'self.wt.updateProgress.connect(self.setProgress)。认为我也需要在那里定义它是愚蠢的。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多