第 6 章: アクション、メニュー、ツールバー
QMainWindowの真価は、メニューバー、ツールバー、ステータスバーといった、一般的なデスクトップアプリケーションが備えるべき UI 要素を簡単に組み込める点にあります。
この章では、これらの要素を効率的に管理するためのQActionという重要なクラスを中心に学びます。
QAction: 抽象的なアクション
アプリケーションには、「ファイルを開く」「コピーする」「終了する」といった様々な「アクション(操作)」があります。 このアクションは、メニューの項目として表示されたり、ツールバーのボタンとして表示されたり、あるいはキーボードショートカットで実行されたりします。
もし、これらを個別のウィジェット(メニュー項目、ツールボタン)として実装すると、同じロジックを複数箇所に書いたり、状態(有効/無効)を同期させたりするのが大変です。
そこで登場するのがQActionです。
QActionは、特定の操作に関するすべての情報(テキスト、アイコン、ショートカットキー、実行すべき処理など)を一つにまとめた、抽象的なオブジェクトです。
ウィジェットではありません。
QActionの利点:
- 再利用性: 一度定義すれば、メニューバーとツールバーの両方に簡単に追加できます。
- 同期:
QActionを無効化(setEnabled(False))すれば、そのアクションが追加されたメニュー項目とツールバーボタンの両方が自動的に無効になります。 - 一元管理: アクションに関するロジックを
triggeredシグナルに接続するだけで済みます。
QMenuBarとQMenu: メニューの実装
QMainWindowにはデフォルトでメニューバーが用意されており、self.menuBar()でアクセスできます。
このメニューバーに対して、QMenu(「ファイル」「編集」などの各メニュー)を追加し、さらにそのQMenuにQActionを追加していきます。
QToolBar: ツールバーの実装
ツールバーもQMainWindowに簡単に追加できます。QToolBarオブジェクトを作成し、self.addToolBar()でメインウィンドウに追加します。
ツールバーにも、メニューと全く同じQActionインスタンスを追加できます。
QStatusBar: ステータスバーの実装
ステータスバーはウィンドウ下部の領域で、self.statusBar()でアクセスできます。
アプリケーションの状態や、マウスカーソルが乗っているメニュー項目の説明などを表示するのに使います。
総合実践:テキストエディタの骨格作成
これらの要素を組み合わせて、簡単なテキストエディタの骨格を作成してみましょう。 ここでは、Qt に組み込まれている標準アイコンを利用して、ファイルを用意しなくても見栄えの良い UI を作成します。
# main_window_skeleton.py
import sys
from PySide6.QtCore import Qt
from PySide6.QtGui import QAction, QIcon, QKeySequence
from PySide6.QtWidgets import (
QApplication, QMainWindow, QToolBar, QTextEdit, QStyle
)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("テキストエディタの骨格")
self.resize(600, 400)
# --- アクションの定義 ---
# 標準アイコンを取得
icon_open = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon)
icon_save = self.style().standardIcon(QStyle.StandardPixmap.SP_DialogSaveButton)
icon_exit = self.style().standardIcon(QStyle.StandardPixmap.SP_DialogCloseButton)
# 「ファイルを開く」アクション
self.open_action = QAction(icon_open, "開く...", self)
self.open_action.setShortcut(QKeySequence.StandardKey.Open) # "Ctrl+O"
self.open_action.setStatusTip("ファイルを開きます")
self.open_action.triggered.connect(self.file_open)
# 「保存」アクション
self.save_action = QAction(icon_save, "保存", self)
self.save_action.setShortcut(QKeySequence.StandardKey.Save) # "Ctrl+S"
self.save_action.setStatusTip("ファイルを保存します")
self.save_action.triggered.connect(self.file_save)
# 「終了」アクション
self.exit_action = QAction(icon_exit, "終了", self)
self.exit_action.setShortcut(QKeySequence.StandardKey.Quit) # "Ctrl+Q"
self.exit_action.setStatusTip("アプリケーションを終了します")
self.exit_action.triggered.connect(self.close) # QMainWindowのcloseスロットを直接呼ぶ
# --- メニューバーの作成 ---
menu = self.menuBar()
file_menu = menu.addMenu("&File") # "&"はアクセスキー(Alt+F)を示す
file_menu.addAction(self.open_action)
file_menu.addAction(self.save_action)
file_menu.addSeparator() # 区切り線
file_menu.addAction(self.exit_action)
# --- ツールバーの作成 ---
toolbar = QToolBar("メインツールバー")
self.addToolBar(toolbar)
toolbar.addAction(self.open_action)
toolbar.addAction(self.save_action)
# --- ステータスバーの作成 ---
self.statusBar().showMessage("準備完了", 3000) # 3秒間表示
# --- 中央ウィジェットの設定 ---
self.editor = QTextEdit()
self.setCentralWidget(self.editor)
# --- スロットメソッド ---
def file_open(self):
self.statusBar().showMessage("ファイルを開くアクションが実行されました")
print("ファイルを開きます...")
def file_save(self):
self.statusBar().showMessage("ファイルを保存するアクションが実行されました")
print("ファイルを保存します...")
if __name__ == "__main__":
app = QApplication(sys.argv)
main_win = MainWindow()
main_win.show()
sys.exit(app.exec())
コードの解説
QAction: 「開く」「保存」「終了」の 3 つのアクションを定義しました。それぞれにアイコン、テキスト、ショートカット、ステータスバーに表示するヒントを設定し、triggeredシグナルを対応するスロットに接続しています。- 標準アイコン:
self.style().standardIcon(...)を使うことで、OS のスタイルに合った標準アイコンを簡単に取得でき、見栄えが良くなります。 - メニューバー:
menuBar()でメニューバーを取得し、addMenuで「File」メニューを追加。そこにaddActionでアクションを登録しています。 - ツールバー:
QToolBarを作成してaddToolBarでウィンドウに追加し、メニューと全く同じQActionインスタンスをaddActionで登録しています。これにより、アイコン付きのボタンが自動で作成されます。 - ステータスバー:
statusBar()で取得し、showMessageで一時的なメッセージを表示しています。また、アクションにsetStatusTipを設定しておくと、ユーザーがメニューやツールバーの項目にマウスを乗せたときに、そのテキストが自動でステータスバーに表示されます。
このコードを実行すると、メニューとツールバーを備えた、アプリケーションらしいウィンドウが表示されるはずです。 アクションが一元管理されていることのメリットを実感してみてください。