윈도우를 생성하고 가장 기본적으로 생성하는 공통 작업이 메뉴만들기일 것이다. 간단하게 메뉴에 대해 알아보려한다.
QMainWindow 는 다음과 같이 영역이 구분되어 있다. ( Qt 공식문서 참조 )

그림에 보이듯이 메뉴는 상단의 Menu Bar 영역에 메뉴가 만들어진다.
메뉴를 만드는 작업은 다음과 같은 과정으로 이루어진다.
- 메뉴바를 만든다.
- File, Edit 같은 최상위(팝업) 메뉴를 추가한다.
- 서브메뉴는 QAction을 생성해서 할당해준다.
메뉴바를 다루기 전에, 지금까지 Qt에 대해 제대로 다룬적이 없으므로 기본 윈도우부터 시작해 보겠다.
import sys
from PySide2.QtWidgets import QMainWindow, QApplication
class MenubarWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # parent, window flags
self._init_ui()
def _init_ui(self):
self.setWindowTitle("Menubar Test")
self.setGeometry(200, 300, 640, 480)
def main():
app = QApplication(sys.argv)
main_window = MenubarWindow()
main_window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
main 함수를 보면, QApplication에 커맨드라인 인자를 넘겨 생성한다. 이것이 Qt의 본체이다. 그 다음, QMainWindow를 상속한 MenubarWindow()를 생성하고 show()를 불러준다. 마지막으로 app.exec_()를 실행해주는데, 모든 UI 및 이벤트 시스템이 그렇듯 이벤트에 반응하는 무한루프가 돌게된다. 모든 윈도우가 종료 이벤트를 받았을 때 종료되는데, 꼭 필요한건 아니지만 시스템에 exit code를 전달하며 종료하고 있다.
Window를 생성하고 따로 등록해주는 작업이 보이지 않는걸로 추측컨데, QMainWindow를 상속받으면 그 생성자 안에서 QApplication에 윈도우를 등록하는 코드가 있을 것이다.
QMainWindow를 상속받은 MenubarWindow에서는 setWindowTitle()과 setGeometry()로 윈도우의 타이틀과 사이즈를 정해주고 있다. 다른 작업이 없어도 가장 기본적인 작업일 것이다. 그 결과물은 다음과 같다.

이제 메뉴바를 만들어보자. 위의 윈도우 코드에서 추가된 부분만 살펴보면 다음과 같다.
def _ui_menu(self):
self.statusBar()
menubar = self.menuBar()
filemenu = menubar.addMenu("&File")
exit_action = QAction(QIcon("../resources/exit_kr.png"), "E&xit", self)
exit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q))
exit_action.setStatusTip("Exit application window")
exit_action.triggered.connect(self.my_exit)
filemenu.addAction(exit_action)
def my_exit(self):
print("menu exit !!")
QApplication.quit()
self.statusBar()는 제일 첫 그림에서 봤듯이 윈도우 하단의 status bar를 생성하는 코드이다.
메뉴바를 생성하는 부분은 self.menuBar()로 메뉴바를 가져오고, addMenu로 최상위 메뉴를 추가한다. addMenu로 추가된 항목은 자기자신은 하는일이 없고 서브메뉴를 팝업시키는 역할을 한다. 메뉴 밑에 추가적인 서브메뉴를 만들고 싶으면 이 메소드를 이용하면 된다.
실제 동작하는 메뉴를 추가하려면 QAction을 만들어야 한다. QAction의 개념은 메뉴바, 툴바등 어느 곳에서든 동일한 동작을 수행하기 위해 만들어진 클래스이다. 커맨드 패턴의 커맨드로 생각하면 쉬울 것 같다. 인자로는 QIcon, name, parent가 들어간다.
setShortcut()을 이용해서 단축키도 지정이 가능하고, setStatusTip을 설정하면 메뉴가 선택됐을 때, status bar에 설명이 표시된다. 마지막으로 메뉴가 실행될 때 동작을 위해서 triggered 시그널을 가지고 있으며 여기에 connect를 이용하여 slot 메소드를 연결한다. 코드에서는 my_exit()가 이에 해당한다.
실행결과는 다음과 같다.

File의 서브메뉴로 Exit가 보이며, QAction에서 설정한 아이콘과 단축키도 보인다. 하단 status bar에는 설정한 문구가 출력되고 있다. 콘솔 출력은 다음과 같다.
menu exit !!
Process finished with exit code 0
메뉴의 triggered 시그널에 연결한 슬롯인 my_exit()가 실행되는걸 확인 할 수 있다.
Python Qt 메뉴생성에 대해 기본적인 걸 정리해봤다. 이를 바탕으로 전체 메뉴를 만들 수 있을 것이다. 메뉴바는 대부분 비슷하고 기능이 추가되는 형태이므로 템플릿처럼 하나 만들어 놓으면 재활용이 가능할 것으로 보인다.