PyQt QtDesigner

1. QtDesigner 소개

지금까지 GUI 프로그램의 기본 개념들을 이해하기 위해 파이썬 코드를 사용하여 UI 요소들을 생성하고 사용하였다. 하지만, 복잡한 UI 인 경우 혹은 UI 작업이 많은 경우, 일일이 UI 요소를 코드에서 생성하는 것은 효율적이지 않다. 이러한 단점을 극복하기 위해 PyQt 안에는 QtDesigner라는 Qt UI Designer 도구가 포함되어 있다. QtDesigner는 UI 위젯들을 드래그-앤-드랍으로 배치할 수 있으며, 각 위젯들의 속성을 쉽게 설정할 수 있다. 이러한 UI 디자인 작업은 .ui 파일(XML 포맷 파일)로 일단 저장되고, PyQt의 Converter를 사용하여 .py 파일로 변환할 수 있다.

2. QtDesigner 실행

QtDesigner 실행파일은 PyQt가 설치된 디렉토리에 있는데, 예를 들어 윈도우즈의 경우 C:\Python34\Lib\site-packages\PyQt4\designer.exe 와 같은 경로를 갖는다 (파이썬이 C:\Python34에 설치된 경우). QtDesigner가 실행되면 아래와 같이 새로운 폼을 만들도록 화면이 나오는데, 여기서 메인윈도우 폼 혹은 다이얼로그 폼 등을 선택할 수 있다.

3. QtDesigner UI 작업

QtDesigner는 크게 세 영역으로 나누어져 있는데, 왼쪽에 여러 위젯들을 모아 놓은 도구상자인 Widget Box가 있고, 중앙에는 WYSIWYG으로 폼(Form)을 조작하는 화면이 있으며, 오른쪽에는 (1)폼 상에 있는 객체들을 트리 구조로 표시한 Object Inspector (2) 각 위젯의 속성들을 설정하는 Property Editor (3) 이벤트(Signal)와 관련 핸들러(Slot)를 표시한 Signal/Slot Editor (그리고 기타 QAction을 편집할 수 있는 Action Editor, 리소스를 관리할 수 있는 Resource Browser)가 있다.

QtDesigner에서의 UI 작업은 Widget Box에서 필요한 위젯 컨트롤을 끌어다 중앙의 폼에 옮겨 놓으면서 하게 된다. 위젯들은 드래그-앤-드랍한 위치에 놓이게 되는데, 필요하면 상단 툴바에 있는 레이아웃 버튼을 눌러 해당 레이아웃에 맞게 자동 조절되게 할 수도 있다. 그리고 꼭 필요한 것은 아니지만, 일반적으로 각 위젯에 대해 필요한 속성을 Property Editor에서 새로 지정해 주게 된다. 특히, 위젯의 objectName 속성은 향후 파이쎤 코드에서 사용될 수 있으므로 의미있는 이름으로 지정해 주는 것이 좋다. 아래는 간단하게 QLabel, QLineEdit, QPushButton 컨트롤을 드래그-앤-드랍하여 만들어 본 화면이다. 참고로 QtDesigner에서 Form - Preview 메뉴를 선택하면 실행시의 폼 화면을 미리 볼 수 있다.

4. UI 파이썬 파일 생성

QtDesigner으로 UI 작업이 모두 끝났으면, File - Save 를 눌러 저장한다. 이때 결과물은 .ui 파일로 저장되는데, 이 .ui 파일은 UI 작업 내용을 XML 형태로 저장한 것이다. 이렇게 저장된 .ui 파일은 다음과 같이 pyuic4 라는 명령을 통해 파이썬 .py 파일로 변환한다. pyuic4은 QtDesigner가 있는 디렉토리와 같은 디렉토리에 있다.

C> pyuic4 ".ui파일명" -o ".py파일명"

5. UI 파이썬 파일 사용

위와 같이 생성된 .py 파일은 UI 폼 (메인윈도우 혹은 다이얼로그) 에 대한 클래스를 담고 있으며, 그 클래스 안에 각 위젯에 대한 인스턴스 변수들을 제공하고 있다. 따라서, 기본적으로 파이썬 프로그램에서 이 UI 폼 클래스의 객체를 생성해서 폼을 화면에 표시하면 된다. 또한, 해당 UI 폼 안에 있는 각 위젯들을 엑세스하여 값을 읽고 쓸 수 있으며, 필요하면 각 위젯에 대해 이벤트핸들러를 추가해 주면 된다.

아래 예제는 QtDesigner로 생성한 UI 다이얼로그를 사용하여 이를 화면에 보여주는 코드이다. 먼저 QtDesigner로부터 생성된 파이썬 UI 파일이 MyDiag.py라고 가정하고, 이 모듈이 아래 코드가 있는 폴더에 복사되어 있다고 가정하자.

from PyQt4.QtGui import *
import sys

# MyDiag.py 모듈 import
import MyDiag

# MyDiag 모듈 안의 Ui_MyDialog 클래스로부터 파생
class XDialog(QDialog, MyDiag.Ui_MyDialog):
    def __init__(self):
        QDialog.__init__(self)
		# setupUi() 메서드는 화면에 다이얼로그 보여줌
        self.setupUi(self)

app = QApplication(sys.argv)
dlg = XDialog()
dlg.show()
app.exec_()

위 예제는 먼저 MyDiag.py 파일을 import해서 로딩한 후, MyDiag.py 모듈 안에 있는 Ui_MyDialog 라는 다이얼로그 클래스를 사용하고 있다. 여기서 Ui_MyDialog는 QtDesigner에서 다이얼로그에 임의로 지정한 objectName으로부터 생성된 이름이다. 파생클래스 XDialog는 두개의 Base 클래스를 갖는데, 하나는 PyQt의 QDialog 클래스이고, 다른 하나는 UI로부터 생성한 MyDiag.Ui_MyDialog 클래스이다. (주: 파이썬은 Multiple Inheritance가 가능하다)
XDialog 클래스의 생성자에서 MyDialog를 화면에 표시하기 위해 Ui_MyDialog 클래스 안에 있는 setupUi() 메서드를 호출하였다.

6. UI 핸들링을 파이썬 코드

UI 폼을 실제 핸들링하는 일은 파이썬 코드로 작성해 준다. 즉, UI 요소들의 값을 읽거나 변경하는 일, 혹은 버튼 컨트롤에 대해 이벤트 핸들러를 추가하는 일 등은 파이썬 코드에서 추가해 준다. 아래 예제를 보면, [저장] 버튼이 클릭되었을 때 saveData() 라는 메서드를 실행하고, [취소] 버튼이 클릭되었을 때 clearData() 라는 메서드를 실행하게 된다.

from PyQt4.QtGui import *
import MyDiag
import sys

class XDialog(QDialog, MyDiag.Ui_MyDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.setupUi(self)

		# 버튼 이벤트 핸들러
        self.btnSave.clicked.connect(self.saveData)
        self.btnCancel.clicked.connect(self.clearData)

	# 저장 버튼 클릭시
    def saveData(self):
        with open("data.csv", "a", encoding="utf-8") as f:
            s = "%s,%s,%s\n" % (self.editName.text(),
                                self.editCompany.text(),
                                self.editAddr.text())
            f.write(s)
        QMessageBox.information(self, "저장", "성공적으로 저장")

	# 취소 버튼 클릭시
    def clearData(self):
        self.editName.clear()
        self.editCompany.clear()
        self.editAddr.clear()

app = QApplication(sys.argv)
dlg = XDialog()
dlg.show()
app.exec_()

저장 버튼 이벤트 핸들러 saveData()에서는 self.editName.text() 와 같이 각 텍스트 위젯으로부터 입력 텍스트를 읽어 데이타 파일에 저장하고 메시지박스를 띄워 표시해 주고 있다. 여기서 데이타 파일은 UTF-8 인코딩을 사용하도록 정의하여 한글OS가 아닌 곳에서도 한글이 깨지지 않게 하였다.
또한 취소 버튼이 클릭되면, clearData() 메서드에서 모든 텍스트 위젯들의 값을 지우도록 코딩하였다.

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