본문 바로가기
Software/Python

파이썬(Python) GUI 프로그래밍의 기본 (PyQt5 Dialog & Main Window 사용)

by lovey25 2019. 4. 19.
반응형

지난 포스팅에서 Python GUI프로그래밍의 묻지마 튜토리얼을 다룬적 있었습니다. 

 

PyQt5로 Python GUI 프로그래밍 시작하기 - Hello World! 출력

Hello world!, 모든 언어의 시작점이죠 지난글에서 준비해둔 파이썬 GUI 개발환경에서 Hello World 출력하기를 실습해 보겠습니다. 새 파이썬 프로젝트 생성 VS를 열어서 새로운 프로젝트를 생성합니다. 파이썬..

kwonkyo.tistory.com

그때는 저도 파이썬의 문법을 하나도 몰랐고 개념도 없었기 때문에 그냥 그런가 보다 했었는데요. 조금 공부를 해보니 코드의 의미가 보이기 시작해서 더 늦기전에 Pyqt5를 사용한 윈도우즈 프로그램의 소스구성에 대한 기본적인 내용을 다루어 보려 합니다. (이미 늦었고 아직도 이해안되는게 있긴 합니다 ㅋ) 

이전 포스팅에서 설명하지 않고 넘어갔던 부분을 다루고 있어서 이번 포스팅과 같이 두 글을 모두 읽어보면 PyQt의 컨셉을 이해하실 수 있으실 겁니다.

PyQt5 Designer를 사용한 GUI프로그래밍의 기본

Pyqt5에서 윈도우 프로그램을 구성하는 방법으로 여러가지가 있는데 그중에서 프로그램창을 다이얼로그로 사용하는 방법과 메인윈도우를 사용하는 방법 두가지에 대해서 알아보겠습니다.

1. 다이얼로그 템플릿 사용

먼저 "ui"파일을 만들어주어야 겠죠. Designer 프로그램을 이용해서 "GUIdlg.ui"라는 파일은 만들어 줍니다. 파일을 생성할때 "Dialog without Buttons" 이라는 탬플릿을 사용해서 만들어 줍니다.

새로운 ui파일이 열리면 다음과 같이 위젯을 배치합니다.

코드내 주석및 하단의 부연설명 참고해 주세요. QPushButton과 QTextEdit를 사용했습니다. 저장을 하고 이제 파이썬 코드를 만들어 줍니다. Visual Studio에서 새로운 프로젝트를 시작해서 아래와 같이 코드를 작성해 줍니다.

실행을 하면 위에서 만든 GUIdlg.ui가 열리고 버튼을 누르면 텍스트박스에 "Hello World!" 가 출력되는 코드입니다. 코드에 대한 설명은 주석과 코드 아래 추가한 부연설명을 참고해 주세요.

#다이얼로그를 사용한 PyQt5사용예제

#1 시스템 변수/파라미터 등을 사용하기 위해서 추가함 argv변수를 사용하기위해서 sys모듈 추가
#   상세변수는 파이썬 공식문서에서 확인
#   https://docs.python.org/ko/3.6/library/sys.html
import sys

#2 QtWidgets의 모든내용을 임포트; Qtwidget은 클래식 데스크탑스타일의 인터페이스를 제공하기위한 클래스를 담고있는 모듈
from PyQt5.QtWidgets import *

#3 uic는 PyQt의 'designer'로 만든 ui파일을 불러오기위해서 사용
#  관련 상세내용은 공식문서에서 확인
#  http://pyqt.sourceforge.net/Docs/PyQt5/designer.html#the-uic-module
from PyQt5 import uic 

#4 "GUI.ui"파일을 불러옴
#  loadUiType은 ui파일을 불어와서 생성된 form과 Qt base 클래스의 튜플을 반환함
form_class = uic.loadUiType("GUIdlg.ui")[0] #form클래스를 변수에 정의

#5 
class MyWindow(QDialog, form_class):
    def __init__(self): 
        super().__init__()                  # 컨스트럭터의 재귀적 실행을 방지하기위한 구문
        self.setupUi(self)                  # 
        self.pushButton.clicked.connect(self.btn_clicked) 

    def btn_clicked(self): 
        self.textEdit.setText("Hello World!") 


if __name__ == "__main__":
            app = QApplication(sys.argv)    # QApplication 객체 생성 https://doc.qt.io/qt-5/qapplication.html#QApplication
            myWindow = MyWindow()           # 위에서 생성한 클래스 생성
            myWindow.show()                 # 
            app.exec_()                     #이벤트 루프 생성

9행, 임포트에관한 간략 설명

간단히 임포트는 'import [모듈이름]’으로 할 수 있습니다. 그런데 여기서는 'from PyQt5.QtWidgets import *' 라는 형태를 사용했네요.  차이점은 묘듈내 정의된 변수, 함수, 클래스에 접근할 때 ‘모듈이름.변수(혹은 함수/클래스)이름’와 같이 사용때마다 모듈 이름을 명시해야 하는가 그렇지 않은가의 차이가 있습니다. 여기서 사용한 'from PyQt5.QtWidgets import *' 는 "PyQt5라는 폴더안에 QtWidgets파일에 있는 전부(*)를 가져오세요" 라는 의미가되고 모듈안에 정의된 모든 변수/함수/클래스는 모듈이름없이 바로 사용이 가능합니다.

그럼 정말 파일이 있는지 찾아가 보겠습니다. 이전 글에서 말씀드렸듯이 저는 Visual Studio를 사용하고 있습니다. (파이썬(Python) 기본개념과 개발환경(Visual Studio & PyQt5) 준비) Visual Studio환경 기준이니 파이참이나 다른 IDE를 사용하시는 분들과는 폴더위치가 다른점 참고해 주세요.

QtWidgets이란 파일의 위치는 "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\Lib\site-packages\PyQt5" 입니다. 그리고 확장자가 py가 아니라 pyd로 되어있습니다.

pyd는 뭘까요? 찾아보니 pyd파일은 윈도의 dll파일과 비슷한 성격의 것이라고 합니다. 성능적인 부분의 이점을 위해서 C언어로 구현을해서 이것을 임포트하는 사용하는 방식이라고 하네요.

35행, 이벤트루프에 관한 설명

이벤트 루프는 말그대로 이벤트를 처리하는 루프인데 계속적으로 반복되는 무한루프의 구조입니다.

파이썬이란 언어는 소스코드를 처음부터 순차적으로 코드를 해석해서 실행하는 언어입니다. 그리고 GUI의 어떤 창이 만들어지는 과정은, 텍스트환경의 기본 프로그램이 실행된상태에서 GUI의 창을 불러와서 수행을 하고 작업이종료되면 텍스트환경의 기본프로그램도 같이 종료되는 그런 과정을 거치게 됩니다. 따라서 우리가 만들어놓은 GUI창을 불러오고나서 GUI창이 의도한 작업을 수행할 수 있도록 원래 텍스트기반의 프로그램이 기다려줄 필요가 있는데 이부분을 처리하는게 이벤트 루프입니다.

루프 상태에서 사용자가 발생한 이벤트를 처리해주고 다음이벤트를 무한히 기다려주기 때문에 GUI창이 살아있으면 프로그램이 같이 대기하고 있게 됩니다.

2. 메인윈도우 템플릿 사용

이번에는 "ui"파일을 만들때 "Main Window" 템플릿을 선택하는 경우입니다. 똑같이 Designer 프로그램을 시작해서 아래와 같이 템플릿을 선택하고 파일을 생성합니다.

그리고 위에서 만든 다이얼로그 템플릿에서와 같이 위젯을 추가해서 배치해 줍니다. 마찬가지로 QPushButton과 QTextEdit입니다.

이번에는 코드를 다음과 같이 작성합니다. 큰 틀에서는 동일한 형태를 가지고 있는데 "MyWindow" 클래스으 매개변수만 달라졌습니다. 

import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic 

Ui_MainWindow, QtBaseClass = uic.loadUiType("GUI.ui")

class MyWindow(QMainWindow):
    def __init__(self): 
        super(MyWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)       
 
        self.ui.pushButton.clicked.connect(self.btn_clicked) 

    def btn_clicked(self): 
        self.ui.textEdit.setText("Hello World!") 


if __name__ == "__main__":
            app = QApplication(sys.argv)
            window = MyWindow()
            window.show()            
            app.exec_()      

 

끝!

반응형

댓글