본문 바로가기

Language/python

Qt Designer와 PySide 사용하여 GUI 프로그래밍 하기(추가)

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.