我想在某些事件上更新进度条的进度。有多个事件/线程,因此与每个事件/线程相关联的进度条。但是当新线程启动时,前一个线程停止更新进度条。这不应该发生。可以使用以下内容:
import sys
from PyQt4 import QtGui, QtCore
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_dialog_progress(object):
def setupUi(self, dialog_progress):
dialog_progress.setObjectName("dialog_progress")
dialog_progress.resize(401, 165)
self.gridLayout = QtGui.QGridLayout(dialog_progress)
self.gridLayout.setObjectName("gridLayout")
self.lblFileName = QtGui.QLabel(dialog_progress)
self.lblFileName.setText("")
self.lblFileName.setObjectName("lblFileName")
self.gridLayout.addWidget(self.lblFileName, 0, 0, 1, 2)
self.pbarFileSize = QtGui.QProgressBar(dialog_progress)
self.pbarFileSize.setProperty("value", 0)
self.pbarFileSize.setObjectName("pbarFileSize")
self.gridLayout.addWidget(self.pbarFileSize, 1, 0, 1, 2)
self.label_2 = QtGui.QLabel(dialog_progress)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
self.pbarTotal = QtGui.QProgressBar(dialog_progress)
self.pbarTotal.setProperty("value", 0)
self.pbarTotal.setObjectName("pbarTotal")
self.gridLayout.addWidget(self.pbarTotal, 3, 0, 1, 2)
self.lblTotal = QtGui.QLabel(dialog_progress)
self.lblTotal.setText("")
self.lblTotal.setObjectName("lblTotal")
self.gridLayout.addWidget(self.lblTotal, 4, 0, 1, 2)
spacerItem = QtGui.QSpacerItem(213, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 6, 0, 1, 1)
spacerItem1 = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem1, 5, 1, 1, 1)
self.btnPbarCancel = QtGui.QPushButton(dialog_progress)
self.btnPbarCancel.setObjectName("btnPbarCancel")
self.gridLayout.addWidget(self.btnPbarCancel, 6, 1, 1, 1)
self.retranslateUi(dialog_progress)
QtCore.QMetaObject.connectSlotsByName(dialog_progress)
def retranslateUi(self, dialog_progress):
dialog_progress.setWindowTitle(QtGui.QApplication.translate("dialog_progress", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("dialog_progress", "Total:", None, QtGui.QApplication.UnicodeUTF8))
self.btnPbarCancel.setText(QtGui.QApplication.translate("dialog_progress", "Cancel", None, QtGui.QApplication.UnicodeUTF8))
class Ui_dialog_file(object):
def setupUi(self, dialog_file):
dialog_file.setObjectName(_fromUtf8("dialog_file"))
dialog_file.resize(101, 59)
self.btnCreate = QtGui.QPushButton(dialog_file)
self.btnCreate.setGeometry(QtCore.QRect(10, 20, 77, 25))
self.btnCreate.setObjectName(_fromUtf8("btnCreate"))
self.retranslateUi(dialog_file)
QtCore.QMetaObject.connectSlotsByName(dialog_file)
def retranslateUi(self, dialog_file):
dialog_file.setWindowTitle(QtGui.QApplication.translate("dialog_file", "file", None, QtGui.QApplication.UnicodeUTF8))
self.btnCreate.setText(QtGui.QApplication.translate("dialog_file", "Create", None, QtGui.QApplication.UnicodeUTF8))
class ProgressDialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent = None)
self.ui = Ui_dialog_progress()
self.ui.setupUi(self)
# self.setWindowModality(QtCore.Qt.ApplicationModal)
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal()
updateFPD = QtCore.pyqtSignal()
updateTPD = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
self.pd = ProgressDialog()
signal = QtCore.SIGNAL("clicked()")
self.pd.ui.btnPbarCancel.connect(self.pd.ui.btnPbarCancel, signal, self.abort)
self.aborted= False
def run(self):
self.trigger.emit()
def abort(self):
self.aborted = True
print "aborted"
self.pd.close()
def setup(self, no):
self.threadNo = no
self.name = "Thread %d"%self.threadNo
class Main(QtGui.QDialog):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.ui = Ui_dialog_file()
self.ui.setupUi(self)
self.ui.btnCreate.clicked.connect(self.start_threads)
self.count = 0
self.threadPool = []
def start_threads(self):
self.mythread = MyThread(self)
self.mythread.setup(self.count)
self.count += 1
self.mythread.trigger.connect(self.pdialog)
self.mythread.start()
self.threadPool.append(self.count)
def abort(self):
self.mythread.stop()
def pdialog(self):
self.mythread.pd.show()
i = 1
self.mythread.pd.ui.pbarTotal.setValue(0)
self.mythread.pd.ui.pbarFileSize.setValue(0)
self.mythread.pd.setWindowTitle(self.mythread.name)
j = 1
while i < 100:
while j <= 100:
self.mythread.pd.ui.lblFileName.setText(self.mythread.name)
self.mythread.pd.ui.pbarFileSize.setValue(j)
print "name: %s, fileprogress: %d"%(self.mythread.name,j)
QtGui.qApp.processEvents()
j += 1
i += 1
j = 1
self.mythread.pd.ui.pbarTotal.setValue(i)
print "name: %s, total progress %d"%(self.mythread.name, i)
QtGui.qApp.processEvents()
if self.mythread.aborted:
return
self.mythread.pd.close()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainwindow = Main()
mainwindow.show()
sys.exit(app.exec_())
请找到我的新代码:
import sys
from PyQt4 import QtGui, QtCore
import time
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_dialog_progress(object):
def setupUi(self, dialog_progress):
dialog_progress.setObjectName("dialog_progress")
dialog_progress.resize(401, 165)
self.gridLayout = QtGui.QGridLayout(dialog_progress)
self.gridLayout.setObjectName("gridLayout")
self.lblFileName = QtGui.QLabel(dialog_progress)
self.lblFileName.setText("")
self.lblFileName.setObjectName("lblFileName")
self.gridLayout.addWidget(self.lblFileName, 0, 0, 1, 2)
self.pbarFileSize = QtGui.QProgressBar(dialog_progress)
self.pbarFileSize.setProperty("value", 0)
self.pbarFileSize.setObjectName("pbarFileSize")
self.gridLayout.addWidget(self.pbarFileSize, 1, 0, 1, 2)
self.label_2 = QtGui.QLabel(dialog_progress)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
self.pbarTotal = QtGui.QProgressBar(dialog_progress)
self.pbarTotal.setProperty("value", 0)
self.pbarTotal.setObjectName("pbarTotal")
self.gridLayout.addWidget(self.pbarTotal, 3, 0, 1, 2)
self.lblTotal = QtGui.QLabel(dialog_progress)
self.lblTotal.setText("")
self.lblTotal.setObjectName("lblTotal")
self.gridLayout.addWidget(self.lblTotal, 4, 0, 1, 2)
spacerItem = QtGui.QSpacerItem(213, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 6, 0, 1, 1)
spacerItem1 = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem1, 5, 1, 1, 1)
self.btnPbarCancel = QtGui.QPushButton(dialog_progress)
self.btnPbarCancel.setObjectName("btnPbarCancel")
self.gridLayout.addWidget(self.btnPbarCancel, 6, 1, 1, 1)
self.retranslateUi(dialog_progress)
QtCore.QMetaObject.connectSlotsByName(dialog_progress)
def retranslateUi(self, dialog_progress):
dialog_progress.setWindowTitle(QtGui.QApplication.translate("dialog_progress", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("dialog_progress", "Total:", None, QtGui.QApplication.UnicodeUTF8))
self.btnPbarCancel.setText(QtGui.QApplication.translate("dialog_progress", "Cancel", None, QtGui.QApplication.UnicodeUTF8))
class Ui_dialog_file(object):
def setupUi(self, dialog_file):
dialog_file.setObjectName(_fromUtf8("dialog_file"))
dialog_file.resize(101, 59)
self.btnCreate = QtGui.QPushButton(dialog_file)
self.btnCreate.setGeometry(QtCore.QRect(10, 20, 77, 25))
self.btnCreate.setObjectName(_fromUtf8("btnCreate"))
self.retranslateUi(dialog_file)
QtCore.QMetaObject.connectSlotsByName(dialog_file)
def retranslateUi(self, dialog_file):
dialog_file.setWindowTitle(QtGui.QApplication.translate("dialog_file", "file", None, QtGui.QApplication.UnicodeUTF8))
self.btnCreate.setText(QtGui.QApplication.translate("dialog_file", "Create", None, QtGui.QApplication.UnicodeUTF8))
class ProgressDialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent=None)
self.ui = Ui_dialog_progress()
self.ui.setupUi(self)
# self.setWindowModality(QtCore.Qt.ApplicationModal)
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal()
updateFPD = QtCore.pyqtSignal(int, QtCore.QString)
updateTPD = QtCore.pyqtSignal(int, QtCore.QString)
showpdSignal = QtCore.pyqtSignal(bool)
def __init__(self, parent=None, no=0):
super(MyThread, self).__init__(parent)
self.aborted = False
self.threadNo = no
# self.name = "Thread %d"%self.threadNo
def run(self):
self.trigger.emit()
def emitSignals(self, iprogress=-99, tprogress=-99, \
updateFPDSignal=True, updateTPDSignal=None, \
showpdSignal=False, peSignal=None, msg=None
):
if updateFPDSignal:
self.updateFPD.emit(iprogress, msg)
if updateTPDSignal:
self.updateTPD.emit(tprogress, msg)
if showpdSignal:
self.showpdSignal.emit(True)
else:
self.showpdSignal.emit(False)
if peSignal:
QtGui.QApplication.processEvents()
def abort(self):
self.aborted = True
print "aborted"
def stop(self):
self.terminate()
class Main(QtGui.QDialog):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.ui = Ui_dialog_file()
self.ui.setupUi(self)
self.ui.btnCreate.clicked.connect(self.start_threads)
self.count = 0
self.threadPool = []
def start_threads(self):
self.mythread = MyThread()
self.pd = ProgressDialog()
self.pd.ui.btnPbarCancel.clicked.connect(self.abort)
self.mythread.trigger.connect(self.pdialog)
self.mythread.updateFPD.connect(self.updateFileProgress)
self.mythread.updateTPD.connect(self.updateTotalProgress)
self.mythread.start()
self.threadPool.append(self.mythread)
def abort(self):
self.pd.close()
self.mythread.aborted = True
def updateFileProgress(self, j, name):
self.pd.ui.lblFileName.setText(name)
self.pd.ui.pbarFileSize.setValue(j)
# print "name: %s, fileprogress: %d" % (name, j)
def updateTotalProgress(self, i, name):
self.pd.ui.pbarTotal.setValue(i)
# print "name: %s, total progress %d" % (name, i)
def showProgressDialog(self, show):
if show:
self.pd.show()
else:
self.pd.close()
def pdialog(self):
self.pd.show()
i = 1
self.threadPool[len(self.threadPool) - 1].emitSignals(iprogress=0 , tprogress=0, updateFPDSignal=True,
updateTPDSignal=True, showpdSignal=True, msg="")
j = 1
while i < 100:
while j <= 100:
self.threadPool[len(self.threadPool) - 1].emitSignals(iprogress=j, updateFPDSignal=True, \
peSignal=True, msg="")
j += 1
i += 1
j = 1
self.threadPool[len(self.threadPool) - 1].emitSignals(tprogress=i, updateTPDSignal=True, \
peSignal=True, msg="")
if self.threadPool[len(self.threadPool) - 1].aborted:
return
self.threadPool[len(self.threadPool) - 1].sleep(2)
self.pd.close()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainwindow = Main()
mainwindow.show()
sys.exit(app.exec_())
答案 0 :(得分:0)
小部件只能由主ui线程控制(即控制主事件循环的线程)。如果一个小部件存在于主线程之外,那么它很可能不会收到任何更新,也不会发布任何事件,例如它被点击。不要让你的线程拥有和/或操纵ui小部件。在这种特殊情况下,您根本不需要MyThread
。
让我举个例子。
import time
import sys
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
progress_changed = QtCore.pyqtSignal(object)
def run(self):
for x in range(101):
#we do not interect with the progress bar directly
self.progress_changed.emit(x)
time.sleep(0.1)
class MyWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.progress_thread1 = MyThread()
self.progress_thread2 = MyThread()
self.progress_bar1 = QtGui.QProgressBar()
self.progress_bar1.setMinimum(0)
self.progress_bar1.setMaximum(100)
self.progress_bar2 = QtGui.QProgressBar()
self.progress_bar2.setMinimum(0)
self.progress_bar2.setMaximum(100)
"""
the progress is emmited through the thread's progress_changed signal
we connect that signal to our updateProgress method which will
be used to set the progress_bar's value
you can also just connect it directly to the progress bar's setValue method
self.progress_thread.progress_changed.connect(self.progress_bar.setValue)
"""
self.progress_thread1.progress_changed.connect(self.updateProgress1)
self.progress_thread2.progress_changed.connect(self.updateProgress2)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(self.progress_bar1)
mainLayout.addWidget(self.progress_bar2)
self.setLayout(mainLayout)
self.progress_thread1.start()
self.progress_thread2.start()
def updateProgress1(self, progress):
self.progress_bar1.setValue(progress)
def updateProgress2(self, progress):
self.progress_bar2.setValue(progress)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
widget = MyWidget()
widget.show()
r = app.exec_()
sys.exit(r)
将其复制到空的python脚本并运行它。