PyQt 예제 3.1.2

이번 글에서는 그룹 액션 및 툴바, 컨텍스트 메뉴, 상태표시줄을 다루어볼 것이다.

그룹 액션은 액션들은 하나의 그룹에 묶어서, 그룹 중에 하나의 액션만 작동하도록 만드는 것이다. 제일 대표적인게, 글의 정렬이다. 왼쪽 정렬이나 가운데 정렬, 오른쪽 정렬 중 동시에 하나만 가능하므로, 이들의 정렬들을 하나로 묶어서 오직 하나의 액션만 작동하도록 해야할 것이다.

여기서는 형식적으로 그룹 액션을 추가해볼 것이다.

(위에서 A Action, B Action, C Action 들이 그룹 액션이다.)

 
        liveDialogAction.setShortcut("Ctrl+L")
        liveDialogHelp = "Live 및 Modaless 대화 상자를 엽니다"
        liveDialogAction.setToolTip(liveDialogHelp)
        liveDialogAction.setStatusTip(liveDialogHelp)
        self.connect(liveDialogAction, SIGNAL("triggered()"), self.LiveCall)

        # Group Action
        messageAAction = QAction("A Action", self)
        messageAAction.setCheckable(True)
        messageAAction.setChecked(True)
        messageBAction = QAction("B Action", self)
        messageBAction.setCheckable(True)
        messageCAction = QAction("C Action", self)
        messageCAction.setCheckable(True)

        self.connect(messageAAction, SIGNAL("toggled(bool)"), self.GroupActionMessage)
        self.connect(messageBAction, SIGNAL("toggled(bool)"), self.GroupActionMessage)
        self.connect(messageCAction, SIGNAL("toggled(bool)"), self.GroupActionMessage)

        groupAction = QActionGroup(self)
        groupAction.addAction(messageAAction)
        groupAction.addAction(messageBAction)
        groupAction.addAction(messageCAction)
        
        ### Menu Bar ###
        # 대화 상자
        dialogAction = self.menuBar().addAction("대화 상자(&A)")
        dialogMenuHelp = "여러 대화 상자 종류들을 포함합니다"
        dialogAction.setToolTip(dialogMenuHelp)
        dialogAction.setStatusTip(dialogMenuHelp)
        dialogMenu = QMenu()
        dialogAction.setMenu(dialogMenu)
        dialogMenu.addAction(simpleDialogAction)
        dialogMenu.addAction(signalDialogAction)
        dialogMenu.addAction(connectDialogAction)
        dialogMenu.addSeparator()
        dialogMenu.addAction(dumbDialogAction)
        dialogMenu.addAction(standardDialogAction)
        dialogMenu.addAction(smartDialogAction)
        dialogMenu.addAction(liveDialogAction)

        ### Tool Bar ###
        # Dialog Tool Bar
        dialogToolBar = self.addToolBar("Dialog")
        dialogToolBar.setObjectName("DialogToolBar")
        dialogToolBar.addAction(simpleDialogAction)
        dialogToolBar.addAction(signalDialogAction)
        dialogToolBar.addAction(connectDialogAction)
        dialogToolBar.addSeparator()
        dialogToolBar.addAction(dumbDialogAction)
        dialogToolBar.addAction(standardDialogAction)
        dialogToolBar.addAction(smartDialogAction)
        dialogToolBar.addAction(liveDialogAction)

        # Group Actoin Tool Bar
        groupActionToolBar = self.addToolBar("GruopAction")
        groupActionToolBar.setObjectName("GroupActionToolBar")
        groupActionToolBar.addAction(messageAAction)
        groupActionToolBar.addAction(messageBAction)
        groupActionToolBar.addAction(messageCAction)
변경된 점만 따로 보겠다. 먼저, 그룹에 추가할 액션이 필요하므로, 액션 3개를 추가하였다. 그리고 액션을 추가하고나서 setCheckable 메소드를 통해서 액션이 체크가 가능하도록 했다.

체크가 가능하다는 것은, 정렬 기능처럼 어느 하나 액션을 선택했을 때, 그 액션이 선택되어 있는 것처럼 보인다는 것이다. 그리고 A 액션에 대해서는 setChecked 메소드로 미리 선택되어 있도록 했다.

그 다음, connect로 액션과 기능을 서로 연결해주어야 하는데, 액션에 대해서 triggered를 사용하지 않고, toggled를 사용했다. triggered를 써도 되지만, toggled를 사용한 이유는 액션이 선택되었는지 확인하기 위해서이다. toggled에 bool 이라고 인자가 쓰여져 있는데, 이것은 시그널이 발생했을 때 bool 인자도 같이 넘겨준다는 것이다.

레퍼런스를 보면 넘겨주는 bool 인자는, 액션이 선택되었는지 아닌지 참 거짓 값을 넘겨주도록 되어 있다. 따라서 연결된 슬롯에서 이 값을 받아서 현재 액션이 선택되었는지, 안 되어있는지 알 수가 있다. 만약, triggered를 쓴다면 메소드 내에서 isChecked 메소드를 통해서 체크 여부를 확인해야 할 것이다.

그 다음으로 QActionGruop 인스턴스를 생성해서, 이곳에 액션들을 추가해주면 액션들이 하나의 그룹으로 지어지게 된다.


이제 액션은 추가 했으므로, 액션과 연결된 슬롯을 보겠다.
 
        if self.liveDialog is None:
            self.liveDialog = introDlg.LiveDialog(self.values, update, self)
        self.liveDialog.show()
        self.liveDialog.raise_()
        self.liveDialog.activateWindow()

    def GroupActionMessage(self, isChecked):
        action = self.sender()
        if not (action and isChecked and isinstance(action, QAction)):
            return
        QMessageBox.about(self, "메시지 박스의 메시지", 
                    "그룹 Action 중 {}이 클릭됨".format(action.text()))
먼저, 이전에 bool의 인자로 넘겨온 값을 isChecked 를 통해서 받았다. 그리고 이 슬롯을 실행시킨 객체를 확인하기 위해서 self.sender 메소드를 통해서 어떤 객체가 시그널을 보냈는지 알아낸다. 그러면 action이 존재하고, 체크가 되어 있으며, 액션이 QAction의 인스턴스인 경우가 아니라면 메소드를 종료시킨다.
(즉, 슬롯으로만 작동시키기 위함이다. 일반적인 메소드 호출이 발생하면 action이 없기 때문에 종료될 것이다.)
그리고 간단한 그룹 액션을 구현하기 우해서 메시지 박스를 띄우는 것으로 마무리 하였다.

메시지 박스를 사용하는 방법은 두 가지가 있는데, 객체를 생성한 다음 호출시키는 방법과, static 메소드를 통해서 잠시 호출하는 방법이다. 전자의 방법은 같은 메시지 박스를 여러번 호출하거나 메시지 박스를 꾸면서 사용할 때 사용하면 되고, 후자의 방법은 기본적으로 제공되는 메시지 박스를, 한 번만 일시적으로 호출할 때 쓰면 좋다.

QMessageBox에는 static 메소드로 구현된 메시지 박스가 5 종류 정도 존재한다. about, critical, information, question, warning이다. 이들은 기본적으로 제공하는 메시지 박스이기 때문에, 제목 표시줄이나 메시지 내용, 버튼 정도의 수정이 가능하다. 여기서는 그냥 표시를 하기 위함이므로 about 메시지 박스를 통해서 메시지를 띄웠다.


이제 액션까지는 만들었고, 그 다음으로 툴바를 추가해서 이 곳에 그룹 액션을 추가해보겠다.
그 전에, 메뉴에 도움말 기능을 추가하는 편법을 소개하겠다. 원래 기본적으로 메뉴에다가 툴팁이나 상태표시줄 팁을 추가해주더라도 나타나지가 않는다. 그러나 이 편법을 통해서 추가할 수가 있기는 하다.

먼저, 메뉴 대신 액션을 만든 다음 액션에 팁을 추가한다. 그리고 메뉴를 생성해서 액션에 그 메뉴를 세팅해준다. dialogAction.setMenu(dialogMenu) 와 같이 액션에 메뉴를 세팅 해주면, 액션이 메뉴처럼 작동되기 때문에 액션의 팁 기능과 메뉴 기능이 모두 구현되게 된다.


툴바의 추가는 현재 메인 윈도우에 addToolBar 메소드를 통해서 툴바를 추가해줄 수 있다. 이 메소드를 수행해주면 메인 윈도우에 툴바가 추가가 된다. 그리고 툴바에 setObjectName을 통해서 객체의 이름을 지정해주자. 이것은 PyQt가 툴바를 저장하고 복원할 수 있도록 해준다.

그 다음, 메뉴에 액션을 추가하듯이 툴바에도 액션을 추가해주면, 간단하게 툴바가 완성이 된다. 그리고 그룹 액션은 따로 툴바를 만들었다.


다음으로, 컨텍스트 메뉴를 추가해보겠다. Context 메뉴는 위젯이나 윈도우에 우클릭을 했을 때 나오는 메뉴를 말한다.
 
        centralWidget = QWidget()
        centralWidget.setLayout(mainLayout)
        self.setCentralWidget(centralWidget)

        self.setWindowTitle("Main Window")

        ### Context Menu ###
        centralWidget.setContextMenuPolicy(Qt.ActionsContextMenu)
        centralWidget.addAction(simpleDialogAction)
        centralWidget.addAction(signalDialogAction)
        centralWidget.addAction(connectDialogAction)
        contextSeparator = QAction(self)
        contextSeparator.setSeparator(True)
        centralWidget.addAction(contextSeparator)
        centralWidget.addAction(dumbDialogAction)
        centralWidget.addAction(standardDialogAction)
        centralWidget.addAction(smartDialogAction)
        centralWidget.addAction(liveDialogAction)
여기서는 컨텍스트 메뉴를 메인 윈도우의 창에 추가하기 위해서, 이전에 메인 윈도우의 중심 위젯으로 설정한 centeralWidget에 액션을 추가했다.

먼저, setContextMenuPolicy를 통해서 위젯에 액션이 추가되었을 때, 어떻게 작동을 해야 하는지 지정했다. Qt.ActionsContextMenu로 설정을 해주면 액션이 추가되었을 때, 그 액션들은 컨텍스트 메뉴의 액션으로 사용이 된다.

그리고 간단히 위젯에 액션을 추가해주면 컨텍스트 메뉴에 액션으로 추가가 된다. 이때, 위젯은 addSeparator 메소드를 가지고 있지 않으므로 분리자를 직접 추가해줄 수는 없다. 따라서 액션을 추가로 생성한 다음, 그 액션을 단순히 분리자로 설정해서(setSeparator) 추가해주면, 컨텍스트 메뉴에 분리자를 추가해줄 수 있다.


마지막으로 상태 표시줄에 대해서 다루어보겠다. 이전에도 상태표시줄을 추가해주었지만, 여기서는 좀 더 추가적인 속성을 다루겠다.
 
        ### Status Bar ###
        statusBar = self.statusBar()
        statusBarLabel = QLabel("상태표시줄")
        statusBarLabel.setFrameStyle(QFrame.StyledPanel|QFrame.Plain)
        statusBar.addPermanentWidget(statusBarLabel)
        statusBar.showMessage("실행 완료", 5000)
이전처럼 상태 표시줄을 추가해주었다. 그리고 상태표시줄에 addPermanentWidget 메소드를 통해서 영구적으로 레이블을 추가해주었다.
그리고 레이블은 setFrameStyle을 통해서 레이블 주변에 테두리가 어떻게 나타날 것인지 꾸며주었다.

이렇게 해두면 상태표시줄에 꾸며진 레이블이 추가가 된다. 그리고 여기서는 다루지 않았지만, 상태표시줄에서 창의 크기 조절 표시를 없앨 수 있다. 창을 최대화 시키지 않을 때, 우측 하단에 보면 창 크기를 조절해줄 수 있도록 표시된 모양이 있다. 이를 제거하는 것이다. 방법은, setSizeGripEnabled 메소드를 통해서 False 값을 넘겨주면 이 모양이 사라진다.


이로써, 메인 위도우에 다양한 기능이 추가되었다. 그러나 아이콘이 없어서 툴바가 너무 길어보이는데, 다음 글에서 아이콘을 추가해서 이를 변경해보겠다.

댓글 없음:

댓글 쓰기