PyQt QtDesigner 메인윈도우

1. QtDesigner 메인윈도우

이번 아티클에서는 QtDesigner를 이용하여 메인윈도우 폼을 만들어 보자. QtDesigner를 실행한 후, Main Window 폼을 선택하여 메인윈도우를 생성하고, 아래 화면과 같이 메뉴, 툴바, 위젯들을 배치한다.

메뉴

메뉴(QMenu)는 "Type Here"를 더블 클릭하고 메뉴 텍스트를 입력하고 Enter를 치면 된다. 상위 메뉴가 입력되면 서브메뉴를 넣을 수 있는 "Type Here"가 표시되며, 필요한 경우 "Add Separator"를 클릭하여 메뉴 분리선을 추가할 수 있다. 이 예제에서는 화면에 보이진 않지만 [파일] 메뉴 밑에 [열기]와 [저장] 서브메뉴를 생성하였다.

툴바

툴바는 메뉴 바로 밑에 위치하는데, 보통 메뉴들 중 중요한 기능들을 툴바에 이미지 버튼으로 표시한다. 툴바를 생성하기 위해서는 폼에서 Rightclick한 후, Add Tool Bar를 선택한다. 툴바가 생성된 후에는 오른쪽 하단의 Action Editor 탭을 선택하고 메뉴에서 이미 생성한 [열기]와 [저장] 아이템을 드래그-앤-드랍으로 툴바에 끌어 놓으면 된다. 이어 툴바 버튼에 이미지를 넣기 위해서 먼저 Qt 리소스를 생성하여 이미지를 리소스에 넣어야 한다.

리소스 생성

QtDesigner에서 이미지 등을 관리하기 위해 리소스 파일을 사용한다. 리소스 파일은 .qrc 확장자를 같는 파일인데, 안에 리소스에 대한 XML 데이타를 가지고 있다. 먼저 리소스 파일을 생성하기 위해, 오른쪽 하단의 Resource Browser 탭을 선택한 후, 연필 모양의 [Edit Resources] 툴바를 선택한다. 이어 좌측 하단의 [New Resource File] 아이콘을 선택하고, 리소스 파일명(예: myres.qrc)을 적는다. 이어 화면 중앙 하단의 [Add Prefix] 아이콘을 눌러 임의의 Prefix명(예:icon)을 적고, 다음 [Add Files] 버튼을 눌러 아이콘 이나 이미지 파일을 import 한다. 이렇게 리소스 파일로 import 된 이미지들은 이미지를 표시할 수 있는 여러 위젯들에 사용될 수 있다. 툴바에서 이미지를 넣기 위해서는 툴바를 선택한 후 Property Editor에서 Icon 속성을 원하는 이미지로 정하면 된다.

기타 위젯들

기타 위젯들로 "키워드" 라는 QLabel, 입력 텍스트 박스인 QLineEdit (objectName: txtKeyword), "검색" 버튼인 QPushButton (btnSearch), 그리고 중앙에 결과를 표시하는 QTableWidget (resultTable) 등을 위 그림과 같이 배치한다. QTableWidget은 선택 후 Rightclick하여 [Edit Items] 메뉴를 선택하고 No와 Title 이라는 컬럼 두 개를 정의한다.

2. 리소스 파이썬 파일 생성

QtDesigner에서 UI가 대충 완성되었으면, 이를 MyWindow.ui라는 파일로 저장하고, 앞 아티클에서 설명한 대로 pyuic4 명령을 사용하여 .py 파이썬 파일을 생성한다. 그런데, 이번 UI는 리소스 파일(.qrc 파일)도 사용하고 있으므로, 이 리소스 파일도 pyrcc4 명령을 사용하여 .py 파이썬 파일으로 생성해 주어야 한다. 파이썬 파일 생성을 위한 pyrcc4 명령은 아래와 같은데, 여기서는 Python 3 를 사용하므로 -py3 옵션을 반드시 지정해 주어야 한다.

C> pyrcc4 "리소스명.qrc" -o "리소스명_rc.py" -py3

여기서 한가지 중요한 사항은 리소스 파일 myres.qrc 에 대해 파이썬 출력 파일명을 myres_rc.py 와 같이 리소스명(myres) 뒤에 "_rc" 를 붙여야 한다는 것이다. 만약 다른 이름을 사용하면 프로그램 실행시 에러가 발생한다.

3. 메인윈도우를 위한 파이썬 코드

이제 UI와 리소스를 각각 파이썬 파일로 변경하였으므로, 마지막 UI를 런치하고 핸들링하는 코드 예제를 보자. 앞 아티클의 다이얼로그와 마찬가지로, MyWindow UI 모듈을 import하여 MyWindow.Ui_MainWindow 클래스를 베이스로한 사용자 정의 메인윈도우 클래스 XWindow를 아래와 같이 정의하였다. 그리고 XWindow의 생성자에서 setupUi() 메서드를 호출하여 UI 초기화를 실행한다. setupUi()으로 UI 초기화를 마친 후, self.show() 호출하면 메인윈도우 화면을 볼 수 있게 된다.

from PyQt4.QtGui import *
import MyWindow
import sys
import pickle

class XWindow(QMainWindow, MyWindow.Ui_MainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)

        # 초기 샘플데이타
        self.initData()

        # 검색 버튼 이벤트 핸들링
        self.btnSearch.clicked.connect(self.search)

        # 메뉴, 툴바 클릭 이벤트 핸들링
        self.actionSave.triggered.connect(self.saveData)
        self.actionOpen.triggered.connect(self.openData)
		
		# 메인윈도우 보이기
        self.show()

    def search(self):
        keyword = self.txtKeyword.text()
        resultData = self.sampleData[keyword]
        self.resultTable.setRowCount(len(resultData))
        row = 0
        for item in resultData:
            self.resultTable.setItem(row, 0, QTableWidgetItem(keyword))
            self.resultTable.setItem(row, 1, QTableWidgetItem(item))
            row += 1

    def initData(self):
        self.sampleData = {
            'Python': ['Fluent Python', 'Python Programming', 'Learning Python'],
            'go' : 'The Go Programming Language',
            'C#' : ['Inside C#', 'C# In Depth'],
            'C' : 'The C Programming Language'
        }

    def saveData(self):
        with open("test.data","wb") as f:
            pickle.dump(self.sampleData, f)
        QMessageBox.information(self, "저장", "데이타 저장됨")
    
    def openData(self):
        with open("test.data","rb") as f:
            self.sampleData = pickle.load(f)
        QMessageBox.information(self, "오픈", "데이타 로딩됨")

app = QApplication(sys.argv)
xwin = XWindow()
app.exec_()

여기서 검색 기능을 추가해 보기 위해, initData() 메서드에 임의의 간단한 Map 데이타를 만들었다 (실제로는 DB나 외부 저장소에서 데이타를 가져올 것임) . 그리고 [검색] 버튼 (btnSearch)의 클릭 이벤트를 search() 메서드에 연결 시켰으며, 이 메서드 않에서 입력 검색어 (txtKeyword.text())에 따라 Map 을 검색해서 결과를 QTableWidget (resultData)에 표시해 주고 있다.

추가적으로 메뉴 및 툴바에 연결된 QAction들 (actionSave, actionOpen)에 대한 이벤트 핸들러 예를 보이기 위하여, 이들의 triggered 이벤트에 각각 saveData(), openData() 핸들러를 연결하였다. QAction의 triggered 이벤트는 메뉴가 클릭되었거나 툴바가 클릭되었을 때, 혹은 해당 단축키 눌려 졌을 때 발생하는 이벤트이다. 여기서는 전체 맥락에 잘 맞진 않지만 테스트로서 Map 데이타를 저장하고 불러오는 코드를 saveData(), openData() 메서드에 넣었다.

아래는 프로그램이 실행되었을 때의 화면이다.

본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.