正在从 Qthread 更新 Python GUI 元素
Updating Python GUI element from Qthread
所以我知道有很多关于使用 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
元素。我知道两个线程都是 运行ning,但我认为我在接收信号时遇到了问题,因为 progressbar
没有更新。我已经尝试了一些事情,但现在我被卡住了。我认为当我尝试将一个值传递给线程以及当我尝试在“setupUi”方法中创建线程的一个实例时,问题就出现了,只是稍后重新定义它。
有谁能帮忙解释一下我的思路错误吗?我正在尝试使用带有线程的信号和槽,所以解释会很好。
您的代码有一些问题,但您已经很接近了。
第一个显而易见的是,您的主线程中有一个带有 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)
希望能解释清楚!
所以我知道有很多关于使用 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
元素。我知道两个线程都是 运行ning,但我认为我在接收信号时遇到了问题,因为 progressbar
没有更新。我已经尝试了一些事情,但现在我被卡住了。我认为当我尝试将一个值传递给线程以及当我尝试在“setupUi”方法中创建线程的一个实例时,问题就出现了,只是稍后重新定义它。
有谁能帮忙解释一下我的思路错误吗?我正在尝试使用带有线程的信号和槽,所以解释会很好。
您的代码有一些问题,但您已经很接近了。
第一个显而易见的是,您的主线程中有一个带有 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)
希望能解释清楚!