所以我知道有很多关于使用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'方法中创建线程的实例时,问题出现了,只是稍后重新定义它。
任何人都可以帮助并解释我在思考中的错误吗?我试图用线程包围信号和插槽,所以解释会很棒。
答案 0 :(得分:2)
您的代码存在一些问题,但是您的代码非常接近。
第一个显而易见的是你的主线程中有一个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)
希望能解释一下!