QGIS 1.8 용 Python 플러그인으로 일부 일괄 처리 도구를 개발하고 있습니다.
도구를 실행하는 동안 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에 의해 타임 스탬프로 태그가 지정되며이 타임 스탬프는 카운터와 함께 "실시간"수신되었음을 나타냅니다. 즉, 작업자 스레드 또는 대화 상자에 의해 큐에 대기되지 않습니다.
로그의 메시지 순서 (다음 실행)는 작업자 스레드가 작업을 시작하기 전에 startButtonHandler가 실행을 완료 함을 나타냅니다 (즉, 스레드가 스레드로 작동 함).
end: startButtonHandler Emit: starting work Emit: 0 ... Emit: 99 Emit: finshed work
작업자 스레드는 GUI 스레드와 리소스를 공유하지 않는 것 같습니다. 위의 소스 끝에 msleep () 및 yieldCurrentThread () 호출을 시도한 두 줄의 주석 처리 된 줄이 있지만 어느 것도 도움이되지 않는 것 같습니다.
이것에 대한 경험이있는 사람이 내 오류를 발견 할 수 있습니까? 나는 그것이 식별되면 수정하기 쉬운 간단하지만 근본적인 실수이기를 바라고 있습니다.