【PyQt6】【サンプル】menuBar(アイコン、ショートカット付き)

はじめに

前回メニューバーを実装しました。
touch-sp.hatenablog.com
今回はアイコン、ショートカットを実装したいと思います。

サンプルスクリプト

from PyQt6.QtCore import QSize
from PyQt6.QtWidgets import QApplication,QLabel,QMainWindow
from PyQt6.QtGui import QAction, QIcon
import os

from collections import OrderedDict

menu_list = OrderedDict(
    ファイル = [
                {'name': '新規', 'shortcut': 'Ctrl+n'}, 
                {'name': '保存', 'shortcut': 'Ctrl+s'}, 
                {'name': '終了', 'icon': 'cross-circle.png'}],
    編集 = [
                {'name': '切り取り', 'shortcut': 'Ctrl+x'}, 
                {'name': 'コピー', 'shortcut': 'Ctrl+c'},
                {'name': '貼り付け', 'shortcut': 'Ctrl+v'}, 
                {'name': '全選択'}],
    ヘルプ = [
                {'name': 'バージョン情報'}]
)

class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setFixedSize(QSize(400,300))
        self.label = QLabel()
        self.setCentralWidget(self.label)

        self.menubar = self.menuBar()
        self.menu = []
        self.action = []
        for key, val in menu_list.items():
            
            self.menu.append(self.menubar.addMenu(key))

            for submenu in val:
                submenu_name = submenu.get('name')
                submenu_shortcut = submenu.get('shortcut')
                submenu_icon = submenu.get('icon')
                self.action.append(QAction(submenu_name))
                if submenu_shortcut is not None:
                    self.action[-1].setShortcut(submenu_shortcut)
                if submenu_icon is not None:
                    icon_dir = os.path.join('icon', submenu_icon)
                    self.action[-1].setIcon(QIcon(icon_dir))
                self.menu[-1].addAction(self.action[-1])
                self.action[-1].triggered.connect(lambda state, x=submenu_name: self.menubarAction(x))
        
    def menubarAction(self, menu_name: str) -> None:
        self.label.setText(f'You pushed {menu_name}!')

if __name__ == "__main__":
    app = QApplication([])
    ex =Window()
    ex.show()
    app.exec()

ポイント

アイコン画像はこちらのものを使わせて頂きました。
p.yusukekamiyamane.com
「icon」フォルダを作成しそちらに使用するアイコンを入れました。

追加したいメニューバーの内容を一つずつ辞書型で定義しました。
キーの種類は「name」「shortcut」「icon」です。
この中で「name」のみ必須になります。

from collections import OrderedDict

menu_list = OrderedDict(
    ファイル = [
                {'name': '新規', 'shortcut': 'Ctrl+n'}, 
                {'name': '保存', 'shortcut': 'Ctrl+s'}, 
                {'name': '終了', 'icon': 'cross-circle.png'}],
    編集 = [
                {'name': '切り取り', 'shortcut': 'Ctrl+x'}, 
                {'name': 'コピー', 'shortcut': 'Ctrl+c'},
                {'name': '貼り付け', 'shortcut': 'Ctrl+v'}, 
                {'name': '全選択'}],
    ヘルプ = [
                {'name': 'バージョン情報'}]
)




アイコン、ショートカットを追加するスクリプトはこのようになります。

submenu_shortcut = submenu.get('shortcut')
if submenu_shortcut is not None:
    self.action[-1].setShortcut(submenu_shortcut)

submenu_icon = submenu.get('icon')
if submenu_icon is not None:
    icon_dir = os.path.join('icon', submenu_icon)
    self.action[-1].setIcon(QIcon(icon_dir))

2022年4月22日追記(PyInstallerでexe化)

pyinstaller menu_sample.py --noconsole

または

pyinstaller menu_sample.py --noconsole --onefile

上記コマンドで問題なくexe化できました。
ただし「icon」フォルダを作成したexeファイルと同じフォルダに配置する必要があります。
つまり--onefileを付けても完全なonefile化はできていませんので注意して下さい。

altgraph==0.17.2
future==0.18.2
pefile==2021.9.3
pyinstaller==5.0
pyinstaller-hooks-contrib==2022.4
PyQt6==6.3.0
PyQt6-Qt6==6.3.0
PyQt6-sip==13.3.1
pywin32-ctypes==0.2.0