ฉันได้พัฒนาเครื่องมือการประมวลผลแบบแบตช์เป็นปลั๊กอินหลามสำหรับ QGIS 1.8
ฉันพบว่าในขณะที่เครื่องมือของฉันกำลังเรียกใช้ GUI จะไม่ตอบสนอง
ภูมิปัญญาทั่วไปคืองานควรทำในเธรดผู้ปฏิบัติงานด้วยข้อมูลสถานะ / ความสมบูรณ์ส่งกลับไปยัง GUI เป็นสัญญาณ
ฉันได้อ่านเอกสารริมตลิ่งแล้วและศึกษาที่มาของ doGeometry.py (การใช้งานจากftools )
การใช้แหล่งข้อมูลเหล่านี้ฉันพยายามสร้างการใช้งานอย่างง่ายเพื่อสำรวจฟังก์ชันการทำงานนี้ก่อนที่จะทำการเปลี่ยนแปลงกับฐานรหัส
โครงสร้างโดยรวมเป็นรายการในเมนูปลั๊กอินที่มีการโต้ตอบกับปุ่มเริ่มและหยุด ปุ่มควบคุมชุดข้อความที่นับถึง 100 โดยส่งสัญญาณกลับไปที่ GUI สำหรับแต่ละหมายเลข GUI ได้รับสัญญาณแต่ละรายการและส่งสตริงที่มีหมายเลขทั้งบันทึกข้อความและชื่อหน้าต่าง
รหัสของการใช้งานนี้อยู่ที่นี่:
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()
น่าเสียดายที่มันไม่ทำงานอย่างที่ฉันหวัง:
- ชื่อหน้าต่างกำลังอัปเดต "สด" ด้วยตัวนับ แต่ถ้าฉันคลิกที่กล่องโต้ตอบมันไม่ตอบสนอง
- บันทึกข้อความไม่ทำงานจนกว่าตัวนับจะสิ้นสุดจากนั้นแสดงข้อความทั้งหมดพร้อมกัน ข้อความเหล่านี้ถูกแท็กด้วยการประทับเวลาโดย QgsMessageLog และการประทับเวลาเหล่านี้บ่งชี้ว่าพวกเขาได้รับ "สด" ด้วยตัวนับนั่นคือพวกเขาไม่ได้ถูกจัดคิวโดยเธรดผู้ปฏิบัติงานหรือไดอะล็อก
ลำดับของข้อความในบันทึก (exerpt follow) บ่งชี้ว่า startButtonHandler ดำเนินการให้เสร็จสิ้นก่อนที่เธรดเธรดผู้ปฏิบัติงานจะทำงานเช่นเธรดจะทำงานเป็นเธรด
end: startButtonHandler Emit: starting work Emit: 0 ... Emit: 99 Emit: finshed work
ดูเหมือนว่าเธรดผู้ปฏิบัติงานจะไม่แชร์ทรัพยากรใด ๆ กับเธรด GUI มีความคิดเห็นสองบรรทัดในตอนท้ายของแหล่งที่มาด้านบนที่ฉันพยายามเรียก msleep () และ yieldCurrentThread () แต่ดูเหมือนจะไม่ช่วยอะไร
ใครบ้างที่มีประสบการณ์ด้วยสิ่งนี้สามารถระบุข้อผิดพลาดของฉันได้หรือไม่ ฉันหวังว่ามันเป็นข้อผิดพลาดที่เรียบง่าย แต่พื้นฐานที่ง่ายต่อการแก้ไขเมื่อมีการระบุ