QGIS 1.8 için bazı toplu işlem araçlarını python eklentileri olarak geliştiriyorum.
Araçlarım çalışırken GUI yanıt vermiyor.
Genel bilgelik, işin bir iş parçacığında yapılması gerektiğidir, durum / tamamlanma bilgileri GUI'ye sinyal olarak geri gönderilir.
İçinden okudum nehir docs ve doGeometry.py kaynağını (bir çalışma uygulaması çalışılan ftools ).
Bu kaynakları kullanarak, yerleşik bir kod tabanında değişiklik yapmadan önce bu işlevselliği keşfetmek için basit bir uygulama oluşturmaya çalıştım.
Genel yapı, eklentiler menüsündeki başlat ve durdur düğmelerini içeren bir iletişim kutusu içeren bir giriştir. Düğmeler, her sayı için GUI'ye bir sinyal göndererek 100'e kadar olan bir iş parçacığını kontrol eder. GUI her sinyali alır ve hem mesaj günlüğünü hem de pencere başlığını içeren bir dize gönderir.
Bu uygulamanın kodu burada:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
class ThreadTest:
def __init__(self, iface):
self.iface = iface
def initGui(self):
self.action = QAction( u"ThreadTest", self.iface.mainWindow())
self.action.triggered.connect(self.run)
self.iface.addPluginToMenu(u"&ThreadTest", self.action)
def unload(self):
self.iface.removePluginMenu(u"&ThreadTest",self.action)
def run(self):
BusyDialog(self.iface.mainWindow())
class BusyDialog(QDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
self.parent = parent
self.setLayout(QVBoxLayout())
self.startButton = QPushButton("Start", self)
self.startButton.clicked.connect(self.startButtonHandler)
self.layout().addWidget(self.startButton)
self.stopButton=QPushButton("Stop", self)
self.stopButton.clicked.connect(self.stopButtonHandler)
self.layout().addWidget(self.stopButton)
self.show()
def startButtonHandler(self, toggle):
self.workerThread = WorkerThread(self.parent)
QObject.connect( self.workerThread, SIGNAL( "killThread(PyQt_PyObject)" ), \
self.killThread )
QObject.connect( self.workerThread, SIGNAL( "echoText(PyQt_PyObject)" ), \
self.setText)
self.workerThread.start(QThread.LowestPriority)
QgsMessageLog.logMessage("end: startButtonHandler")
def stopButtonHandler(self, toggle):
self.killThread()
def setText(self, text):
QgsMessageLog.logMessage(str(text))
self.setWindowTitle(text)
def killThread(self):
if self.workerThread.isRunning():
self.workerThread.exit(0)
class WorkerThread(QThread):
def __init__(self, parent):
QThread.__init__(self,parent)
def run(self):
self.emit( SIGNAL( "echoText(PyQt_PyObject)" ), "Emit: starting work" )
self.doLotsOfWork()
self.emit( SIGNAL( "echoText(PyQt_PyObject)" ), "Emit: finshed work" )
self.emit( SIGNAL( "killThread(PyQt_PyObject)"), "OK")
def doLotsOfWork(self):
count=0
while count < 100:
self.emit( SIGNAL( "echoText(PyQt_PyObject)" ), "Emit: " + str(count) )
count += 1
# if self.msleep(10):
# return
# QThread.yieldCurrentThread()
Ne yazık ki umduğum gibi sessiz çalışma:
- Pencere başlığı sayaçla "canlı" olarak güncelleniyor, ancak iletişim kutusunu tıklarsam yanıt vermez.
- Mesaj günlüğü sayaç sona erene kadar devre dışı kalır, ardından tüm mesajları bir kerede sunar. Bu mesajlar QgsMessageLog tarafından bir zaman damgası ile etiketlenir ve bu zaman damgaları sayaç ile "canlı" olarak alındıklarını, yani ya iş parçacığı ya da iletişim kutusu tarafından sıraya alınmadıklarını gösterir.
Günlükteki iletilerin sırası (exerpt izler), işçi iş parçacığı gelmeden önce startButtonHandler'ın yürütmeyi tamamladığını, yani iş parçacığının bir iş parçacığı gibi davrandığını gösterir.
end: startButtonHandler Emit: starting work Emit: 0 ... Emit: 99 Emit: finshed work
İşçi iş parçacığı sadece GUI iş parçacığı ile herhangi bir kaynak paylaşmıyor gibi görünüyor. Yukarıdaki kaynağın sonunda msleep () ve giveCurrentThread () çağırmayı denedim, ancak ikisi de yardımcı görünmüyordu.
Bu konuda herhangi bir deneyimi olan herhangi biri benim hata tespit edebilirsiniz? Bir kez tanımlandıktan sonra düzeltilmesi kolay olan basit ama temel bir hata olduğunu umuyorum.