PyQt 예제 3.3.2

이번 예제에서는 코드를 좀 더 깔끔하게 다듬는 작업을 진행하였다. 새로운 내용은 없지만, 중복 코드를 축약하고 더 간편하게 변경시켰다.

먼저, 폼 레이아웃에서 QLabel를 대체하는 작업을 하였다. 폼 레이아웃을 생성할 때, 레이블 부분을 QLabel을 사용하지 않고 문자열을 사용해서 바로 레이블을 명시할 수 있다.

여기서는 QLabel의 특성(글씨 크기나 색상 변경 등...)들을 사용하지 않기 때문에 코드를 변경하였다.

그리고 폼 레이아웃에 레이블과 필드를 추가할 때 공통적으로 addrow를 사용하기 때문에 여러 레이블과 필드 추가를 간편하기 위해서 AddRows라는 메소드를 추가하였다.

즉, 폼 레이아웃을 명시하고, 레이블과 필드를 튜플로 묶어서 넘겨주면 이를 for 문으로 처리하게 끔 하였다.

AddRows 메소드는 아래와 같이 되어 있다.
def AddRows(self, layout, rows):
        for row in rows:
            layout.addRow(*row)
self.AddRows(폼 레이아웃, ((레이블1, 필드1), (레이블2, 필드2))) 형식으로 넘겨 주면 rows에는 ((레이블1, 필드1), (레이블2, 필드2))이 들어가게 되고, row에 (레이블1, 필드1)이 대입되어 *row를 통해서 언패킹 하도록 하였다.

실제 사용으로는 아래와 같이 변경하였다.
######## 변경 전
        buttonLayout.addRow(mainButtonLabel, self.mainButton)
        buttonLayout.addRow(mainCheckBoxLabel, self.mainCheckBox)

######## 변경 후
        self.AddRows(buttonLayout, (
                ("버튼: ", self.mainButton),
                ("체크 상자: ", self.mainCheckBox)))
레이블 객체들은 모두 제거하였고, 이를 문자열로 대체한 다음, 위에서 설명한 방식으로 레이아웃을 추가하였다.


그 다음으로는 책에서 사용한 방법으로, 액션을 생성하는 부분을 변경하였다. 여기서는 액션들이 대부분 공통적인 요소를 사용하면서 생성되기 때문에, 일일이 액션 설정을 따로 하지 않고, 함수를 통해서 액션을 설정하도록 하였다.
#
    def CreateAction(self, name, icon=None, shortcut=None, tipHelp=None, 
                            slot=None, checkable=False, signal="triggered()"):
        action = QAction(name, self)
        if icon:
            action.setIcon(QIcon(icon))
        if shortcut:
            action.setShortcut(shortcut)
        if tipHelp:
            action.setToolTip(tipHelp)
            action.setStatusTip(tipHelp)
        if slot:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)

        return action
CreateAction이라는 메소드를 생성하였다. 액션의 이름을 name으로 받고, 현재 클래스에 간단한 액션을 생성한다. 그 다음으로 액션들의 요소를 설정하기 위해서 각 인자가 None이 아닌 값으로 주어질 경우 이를 설정하도록 하였다.

이와 같이 설정할 경우, triggered()와 같이 기본적으로 사용되는 요소는 쓰지 않아도 되므로 더 축약해서 표현할 수 있다.

이때, 인자의 순서를 적절하게 정해주어야, 메소드를 쓸 때 인자를 명시하지 않고도 메소드를 사용할 수 있다.

실제로 변경된 표현은 아래와 같다.
######## 변경 전
        simpleDialogAction = QAction(QIcon(":simpleDialogIcon.png"), 
                                            "단순 대화상자", self)
        simpleDialogAction.setShortcut("Ctrl+S")
        simpleDialogHelp = "단순한 대화 상자를 엽니다"
        simpleDialogAction.setToolTip(simpleDialogHelp)
        simpleDialogAction.setStatusTip(simpleDialogHelp)
        self.connect(simpleDialogAction, SIGNAL("triggered()"),
                        lambda : sscDlg.SimpleDialog(self).exec_())

######## 변경 후
        simpleDialogAction = self.CreateAction("단순 대화상자",
                                ":simpleDialogIcon.png", "Ctrl+S",
                                "단순한 대화 상자를 엽니다",
                                lambda: sscDlg.SimpleDialog(self).exec_())
코드를 보면 알 수 있듯이, 훨씬 간편하게 액션을 생성할 수 있게 되었다.


그 다음으로는, AddRows로 레이아웃을 추가하듯이 메뉴에 여러 액션들을 한 번에 추가할 수 있도록 하였다.
def AddActions(self, target, actions):
        for action in actions:
            if action:
                target.addAction(action)
            else:
                target.addSeparator()
target은 일반 메뉴가 될 수 있고, 컨텍스트 메뉴가 될 수도 있다. 즉, addAction을 가진 경우에 사용할 수 있다.
######## 변경 전
        dialogMenu.addAction(simpleDialogAction)
        dialogMenu.addAction(signalDialogAction)
        dialogMenu.addAction(connectDialogAction)
        dialogMenu.addSeparator()
        dialogMenu.addAction(dumbDialogAction)
        dialogMenu.addAction(standardDialogAction)
        dialogMenu.addAction(smartDialogAction)
        dialogMenu.addAction(liveDialogAction)
######## 변경 후
        self.AddActions(dialogMenu, (simpleDialogAction, signalDialogAction,
            connectDialogAction, None, dumbDialogAction, standardDialogAction,
            smartDialogAction, liveDialogAction))
None 의 경우 분리자를 추가하기 위해서 주어진 값이다. 단, 컨텍스트 메뉴의 경우에는 addSeparator 메소드가 없기 때문에 분리자를 추가하려면 Separator를 생성한 후에 일반 액션처럼 추가를 해주어야 한다.

나머지 변경된 코드는 아래 페이지를 참고하면 된다.
https://github.com/bluekyu/PyQt-Examples/blob/a62b7fd0ef56235796724f958b269d28d89dc023/mainWindow.pyw

댓글 없음:

댓글 쓰기