2013-12-18 31 views
15

Bu kodu vardır: o uygulamayı donup kalmamasıPython Pyside ve İlerleme Çubuğu Threading

from PySide import QtCore, QtGui 
import time 

class Ui_Dialog(object): 
    def setupUi(self, Dialog): 
     Dialog.setObjectName("Dialog") 
     Dialog.resize(400, 133) 
     self.progressBar = QtGui.QProgressBar(Dialog) 
     self.progressBar.setGeometry(QtCore.QRect(20, 10, 361, 23)) 
     self.progressBar.setProperty("value", 24) 
     self.progressBar.setObjectName("progressBar") 
     self.pushButton = QtGui.QPushButton(Dialog) 
     self.pushButton.setGeometry(QtCore.QRect(20, 40, 361, 61)) 
     self.pushButton.setObjectName("pushButton") 

     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.progressBar.setValue(0) 
     self.pushButton.clicked.connect(self.progress) 

    def progress(self): 
     self.progressBar.minimum = 1 
     self.progressBar.maximum = 100 
     for i in range(1, 101): 
      self.progressBar.setValue(i) 
      time.sleep(0.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_()) 

Ben, ayrı bir konu ilerleme çubuğu bulunur etmek istiyorum, ama gibi olamaz nasıl yapılacağını bul.

Lütfen yardım edebilir misiniz?

cevap

25

Yanlış olabileceğinizi düşünüyorum. Yaptığınız işin ayrı bir iş parçacığı olmasını istiyorsunuz, böylece uygulamayı dondurmuyor. Ancak, aynı zamanda ilerleme çubuğunu da güncelleyebilmek istersiniz. Bunu, QThread kullanarak bir işçi sınıfı oluşturarak başarabilirsiniz. QThreads, UI'nizin dinleyebildiği ve uygun şekilde hareket edebileceği sinyaller verebilir.

İlk önce, işçi sınıfınızı oluşturalım.

#Inherit from QThread 
class Worker(QtCore.QThread): 

    #This is the signal that will be emitted during the processing. 
    #By including int as an argument, it lets the signal know to expect 
    #an integer argument when emitting. 
    updateProgress = QtCore.Signal(int) 

    #You can do any extra things in this init you need, but for this example 
    #nothing else needs to be done expect call the super's init 
    def __init__(self): 
     QtCore.QThread.__init__(self) 

    #A QThread is run by calling it's start() function, which calls this run() 
    #function in it's own "thread". 
    def run(self): 
     #Notice this is the same thing you were doing in your progress() function 
     for i in range(1, 101): 
      #Emit the signal so it can be received on the UI side. 
      self.updateProgress.emit(i) 
      time.sleep(0.1) 

Artık bir işçi sınıfınız olduğu için, bundan yararlanmanın zamanı geldi. Yayılan sinyalleri işlemek için Ui_Dialog sınıfınızda yeni bir işlev oluşturmak isteyeceksiniz.

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

Oradayken, progress() işlevinizi kaldırabilirsiniz. retranslateUi() yılında

Eğer setupUI() işlevinde Nihayet

self.pushButton.clicked.connect(self.worker.start) 

e

self.pushButton.clicked.connect(self.progress) 

gelen düğme olay işleyicisi güncellemek isteyecektir, kendi işçi sınıfının bir örneğini oluşturmak gerekir ve bu sinyali setProgress() işlevinize bağlayın. Bundan önce

:

self.retranslateUi(Dialog) 

ekleyin:

from PySide import QtCore, QtGui 
import time 


class Ui_Dialog(object): 
    def setupUi(self, Dialog): 
     Dialog.setObjectName("Dialog") 
     Dialog.resize(400, 133) 
     self.progressBar = QtGui.QProgressBar(Dialog) 
     self.progressBar.setGeometry(QtCore.QRect(20, 10, 361, 23)) 
     self.progressBar.setProperty("value", 24) 
     self.progressBar.setObjectName("progressBar") 
     self.pushButton = QtGui.QPushButton(Dialog) 
     self.pushButton.setGeometry(QtCore.QRect(20, 40, 361, 61)) 
     self.pushButton.setObjectName("pushButton") 

     self.worker = Worker() 
     self.worker.updateProgress.connect(self.setProgress) 

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

     self.progressBar.minimum = 1 
     self.progressBar.maximum = 100 

    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.progressBar.setValue(0) 
     self.pushButton.clicked.connect(self.worker.start) 

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

#Inherit from QThread 
class Worker(QtCore.QThread): 

    #This is the signal that will be emitted during the processing. 
    #By including int as an argument, it lets the signal know to expect 
    #an integer argument when emitting. 
    updateProgress = QtCore.Signal(int) 

    #You can do any extra things in this init you need, but for this example 
    #nothing else needs to be done expect call the super's init 
    def __init__(self): 
     QtCore.QThread.__init__(self) 

    #A QThread is run by calling it's start() function, which calls this run() 
    #function in it's own "thread". 
    def run(self): 
     #Notice this is the same thing you were doing in your progress() function 
     for i in range(1, 101): 
      #Emit the signal so it can be received on the UI side. 
      self.updateProgress.emit(i) 
      time.sleep(0.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_()) 

: Burada

self.worker = Worker() 
self.worker.updateProgress.connect(self.setProgress) 
son koddurQThreads, otomatik olarak yayılan bazı sinyallere sahiptir. Onları görebilir ve QThreads in the documentation

+1

Yup, bu şekilde olmasını istedim, teşekkürler! – Benny

9

hakkında daha fazla bilgi Her zaman böyle şeyler için çoklu iş parçacığı kullanmanız gerektiğini düşünmek bir hatadır.

Uzun süren görevinizi bir dizi küçük aşamaya ayırabiliyorsanız, tek yapmanız gereken, bekleyen tüm olayların GUI'nin yanıt vermeye devam etmesi için yeterince sık sık işlendiğinden emin olmaktır.Bu böyle, processEvents kullanarak ana GUI iplik içinde itibaren güvenle yapılabilir:

for i in range(1, 101): 
     self.progressBar.setValue(i) 
     QtGui.qApp.processEvents() 
     time.sleep(0.1) 

Verilen bu basitlik, en azından çok gibi çok daha ağır bir çözüm gözle önce bu tekniği dikkate hep değer var -threading veya çoklu işleme.

+0

Bu çok kolay oldu! sorunumu çözdü! – user1036908