Qt Designer와 PySide 사용하여 GUI 프로그래밍 하기 2/2 에서 보았듯이 GUI에서 signal 처리시 시간이 많이 걸리면 전체 GUI가 먹통이 되는 현상이 있다. 이걸 해결하기 위하여 QThread를 사용하여 수정해 본다.
아래와 같이 소스코드를 수정해 보았다. (파란색 부분이 수정 및 추가된 부분이다.)
import sys import time import TestWidget class TestMainDialog2(QDialog, TestWidget.Ui_Form): def __init__(self, parent=None): super(TestMainDialog2, self).__init__(parent) self.setupUi(self) self.connect(self.pushButton, SIGNAL("clicked()"), self.showMessage) #self.pushButton.clicked.connect(self.showMessage) self.workerThread = WorkerThread() self.connect(self.workerThread, SIGNAL("threadDone()"), self.showThreadDone) def showMessage(self): self.workerThread.start() QMessageBox.information(self, "Info", "You clicked pushButton.") def showThreadDone(self): QMessageBox.warning(self, "Warining", "Thread done.") class WorkerThread(QThread): def __init__(self, parent=None): super(WorkerThread, self).__init__(parent) def run(self): time.sleep(5) self.emit(SIGNAL("threadDone()")) if __name__ == "__main__": app = QApplication(sys.argv) diag = TestMainDialog2() diag.show() sys.exit(app.exec_())
1. WorkerThread를 만든다. QThread를 상속받게 하여 signal을 발생할 수 있도록 한다. 쓰레드가 종료시 커스텀 signal인 "threadDone()" 를 발행한다.
2. WorkerThread의 객체를 멤버 변수에 추가하고, 커스텀 signal인 "threadDone()"과 showThreadDone 함수를 연결한다.
이로써, 시간이 걸리는 일은 WorkerThread에서 처리하도록 하여, GUI는 제 기능을 수행할 수 있게 된다.
참고로, youtube에서는 "threadDone()" signal을 처리하기 위하여, Qt.DirectConnection을 추가하도록 제시하였는데 내 컴퓨터에서는 관련 옵션을 주면 아래와 같은 로그를 내면서 GUI 프로그램이 죽었다. 참고하자.
D:\JoohyunLee\Documents\Workspace_python\ui_test2>python TestMainDialog.py
QObject::setParent: Cannot set parent, new parent is in a different thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject::startTimer: timers cannot be started from another thread
QApplication: Object event filter cannot be in a different thread.
...
QObject::startTimer: timers cannot be started from another thread
QApplication: Object event filter cannot be in a different thread.
QObject::startTimer: timers cannot be started from another thread
QApplication: Object event filter cannot be in a different thread.
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject::startTimer: timers cannot be started from another thread
QApplication: Object event filter cannot be in a different thread.