PyQt

【PyQt】QMainWindowを継承した画面開発のテンプレート

【PyQt】QMainWindowを継承した画面開発のテンプレート

PythonのGUIツールキットであるPyQtで、QMainWindowを継承して画面開発する際の画面テンプレートを紹介します。

PyQt

PyQtは、クロスプラットフォームなGUI開発ができるツールキットで、Windows、Linux、Mac等の様々なOSで動作可能なGUIプログラムを作成することができます。PyQtの概要については「PyQt概要 ~PythonでGUI開発~」でまとめていますので興味があれば参考にしてください。

PyQtを用いた開発では一般的にQWidgetQMainWindowを継承してメイン画面を作成して開発します。シンプルな入力や出力のアプリケーションであればQWidgetを継承すればよいですし、ツールバー等を含むアプリケーションであればQMainWindowを継承して開発します。

画面開発をする際に画面開発のテンプレートとなるようなプログラムがあると新規開発をしようとするときにすぐに着手できて便利です。

本記事では、QMainWindowを使った場合の画面テンプレートプログラムを紹介します。また、実際に簡易テキストエディタを作ることでQMainWindowを使うことで簡単にツールバー等を含む本格的なアプリケーションを開発できることを説明します。

なお、QWidgetを継承した場合の画面テンプレートは「QWidgetを継承した画面開発のテンプレート」でまとめていますので興味があれば参考にしてください。

QMainWindowを継承した画面開発テンプレート

以降では、QMainWindowを継承した画面開発テンプレートプログラムを紹介します。本記事ではPyQt6を利用していますが、PyQt5でも同様の構成が使用できます。

画面開発テンプレート (QMainWindow)

QMainWindowを継承する場合の画面テンプレートプログラムを以下に示します。内容の詳細については以降の節で説明していこうと思います。

import sys

from PyQt6 import QtCore as qtc
from PyQt6 import QtGui as qtg
from PyQt6 import QtWidgets as qtw


class MainWindow(qtw.QMainWindow):
    """メインウィンドウ"""

    def __init__(self):
        super().__init__()
        # 画面タイトルの設定
        self.setWindowTitle("ウィンドウタイトル")
        # 画面サイズの設定
        self.resize(640, 360)

        # ========== ここに画面要素を記載する ==========
        # ・メニューの追加
        # ・メニュー内のアクションの追加
        # ・ツールバーの追加
        # ・ステータスバーの追加
        # ...
        # ============================================

        # 画面表示
        self.show()


def main():
    """メイン関数"""
    app = qtw.QApplication(sys.argv)
    mv = MainWindow()
    sys.exit(app.exec())


if __name__ == "__main__":
    main()

【実行結果】

QMainWindowを継承した画面テンプレート

詳細説明

以降では、上記で紹介したテンプレートプログラムの各パートについて紹介していきます。

インポート

import sys

from PyQt6 import QtCore as qtc
from PyQt6 import QtGui as qtg
from PyQt6 import QtWidgets as qtw

インポートでは主に上記をインポートします。PyQtからは「QtCore」「QtGui」「QtWidget」をそれぞれqtc, qtg, qtwという別名でインポートしています。

  • QtCore:Qtを利用するためのコアの設定などの定義がされています。
  • QtGui:Qtの画面設定関連の定義がされています。
  • QtWidget:Qtの画面構成要素のウィジェットが定義されています。

今回のプログラムは画面構成の細かなプログラムは書いていないのでQtCore, QtGuiは使っていませんが、上記の3つは画面構築時にほぼ必ず使いますので定型としてインポートしておきましょう。

メイン処理

def main():
    """メイン関数"""
    app = qtw.QApplication(sys.argv)
    mv = MainWindow()
    sys.exit(app.exec())


if __name__ == "__main__":
    main()

上記の部分は、画面表示のためのメイン関数です。この部分の書き方は定型の書き方ということで理解してもらってよいかと思います。

QApplicationクラスがアプリケーションのためのクラスで、sys.argv経由で引数を取得してアプリケーションを構築します。app.exec()で画面描画の処理ループが開始します。画面側で終了の信号が返却されるとsys.exit()に渡されて画面が終了するという流れです。

mv = MainWindow()の部分が開発者が自分で独自に開発する画面のクラスを定義している部分です。MainWindowクラスの作成方法については以降で説明します。

メインウィンドウクラス

class MainWindow(qtw.QMainWindow):
    """メインウィンドウ"""

    def __init__(self):
        super().__init__()
        # 画面タイトルの設定
        self.setWindowTitle("ウィンドウタイトル")
        # 画面サイズの設定
        self.resize(640, 360)

        # ========== ここに画面要素を記載する ==========
        # ・メニューの追加
        # ・メニュー内のアクションの追加
        # ・ツールバーの追加
        # ・ステータスバーの追加
        # ...
        # ============================================

        # 画面表示
        self.show()

上記の部分が、画面の構成要素を構築している部分で、qtw(=PyQt6.QtWidgets)の中にあるQMainWindowクラスを継承して画面を開発します。もう少し細かく見ていきましょう

    def __init__(self):
        super().__init__()

コンストラクタ__init__では、継承元のコンストラクタであるsuper().__init__()を呼び出して画面に必要な要素を用意します。

        # 画面タイトルの設定
        self.setWindowTitle("ウィンドウタイトル")

画面タイトルについては、上記のようにself.setWindowTitleで文字列を渡すことで、画面表示時のタイトルを設定できます。selfというのは、メインウィンドウの自分自身です。今後画面要素を定義する際の親画面となって、各画面要素に渡したりするので覚えておきましょう。

        # 画面サイズの設定
        self.resize(640, 360)

初期表示の画面サイズはself.resizeで設定ができます。これから開発する画面サイズを指定しましょう。画面サイズは以下の表が参考になるかと思います。

サイズクラスブレークポイント一般的な画面サイズデバイスウィンドウサイズ
最大640px20″から65″テレビ320×569、360×640、480×854
中間641-1007px7~12インチタブレット960×540
1008px以上13インチ以上PC、ノートPC、Surface Hub1024×640、1366×768、1920×1080
【引用】画面のサイズとブレークポイント

画面を用意したら具体的に画面要素を定義していくわけですが、画面要素は以下の部分に記載をしていきます。

        # ========== ここに画面要素を記載する ==========
        # ・メニューの追加
        # ・メニュー内のアクションの追加
        # ・ツールバーの追加
        # ・ステータスバーの追加
        # ...
        # ============================================

QWidgetを継承する場合と異なり、QMainWindowを継承した場合は、メニューやツールバー、ステータスバー等を追加して本格的なアプリケーションを開発できますが、ここに記載するとごちゃごちゃしてしまいますので、以降の簡易テキストエディタ開発例の説明時に紹介していきます。

まず開発テンプレートという意味では、この部分に色々と追加していくことで実装していくのだということをご理解いただければよいかと思います。

        # 画面表示
        self.show()

注意点として、最後にshow()を呼び出さないと画面表示されません。メインウィンドウであるself.show()を呼び出すことで、その子として紐づけられているQLabel等のWidgetの要素も含めて画面表示されます。

画面動作の開発

上記でQMainWindowを継承したプログラムのベース部分となるテンプレートを紹介してきました。

より細部の画面実装は、各種ウィジェットを作成、レイアウトを使って配置、各ウィジェットにおけるシグナルとスロットを接続といったことを行っていきます。

開発に必要となる基本として、以下のページの内容が参考になるかと思いますので、あわせて参考にしていただければと思います。

QMainWindowを継承した画面開発テンプレートを用いた実装例 ~簡易テキストエディタ~

これまでで、QMainWindowを使った画面開発のテンプレートを紹介してきました。

もう少し具体的に簡易テキストエディタを作ってみることで、本格的なアプリケーション開発が簡単に実装できることを紹介していきたいと思います。以下のプログラムをベースの参考にしてもらってプログラム開発してもらうのもよいかなと思っています。

以降で紹介するプログラムでは以下のような画面を作成します。

QMainWindow 簡易テキストエディタ

アプリケーションでよく見るようなメニューバーやツールバー、ステータスバーを含むようなアプリケーションで、中心のwidget(central widget)としてQTextEditによるテキスト入力欄があるような画面構成になっています。以下実装例と詳細説明をしていきます。

実装例

以下にプログラムの実装例を示します。一旦すべてのコードを示していますが、詳細については以降の節で部分ごとに紹介していきます。

import sys

from PyQt6 import QtCore as qtc
from PyQt6 import QtGui as qtg
from PyQt6 import QtWidgets as qtw


class MainWindow(qtw.QMainWindow):
    """メインウィンドウ"""

    def __init__(self):
        super().__init__()
        # 画面タイトルの設定
        self.setWindowTitle("Simple Text Editor")
        # 画面サイズの設定
        self.resize(640, 360)
        # central widgetの設定
        self.text_edit = qtw.QTextEdit()
        self.setCentralWidget(self.text_edit)

        # =============== メニューバー =================
        # ===== メニュー項目の追加
        # [ファイル]メニュー
        file_menu = self.menuBar().addMenu("ファイル(&F)")
        # [編集]メニュー
        edit_menu = self.menuBar().addMenu("編集(&E)")
        # [ヘルプ]メニュー
        help_menu = self.menuBar().addMenu("ヘルプ(&H)")
        # ...他メニューも必要に応じて追加

        # ===== [ファイル]メニューのアクションの追加
        # [ファイルを開く...] アクション
        open_action = qtg.QAction(
            self.style().standardIcon(qtw.QStyle.StandardPixmap.SP_DirOpenIcon),
            "ファイルを開く...",
            self,
            triggered=self.open_file,
            shortcut=qtg.QKeySequence("Ctrl+O"),
        )
        file_menu.addAction(open_action)

        # [保存] アクション
        save_action = qtg.QAction(
            self.style().standardIcon(qtw.QStyle.StandardPixmap.SP_DriveHDIcon),
            "保存",
            self,
            triggered=self.save_file,
            shortcut=qtg.QKeySequence("Ctrl+S"),
        )
        file_menu.addAction(save_action)

        # [終了] アクション
        quit_action = file_menu.addAction("終了", self.close)
        # ...他アクションも必要に応じて追加

        # ===== [編集]メニューのアクション追加
        # [元に戻す] アクション
        undo_action = qtg.QAction(
            "元に戻す",
            self,
            triggered=self.text_edit.undo,
            shortcut=qtg.QKeySequence("Ctrl+Z"),
        )
        edit_menu.addAction(undo_action)

        # [やり直し] アクション
        redo_action = qtg.QAction(
            "やり直し",
            self,
            triggered=self.text_edit.redo,
            shortcut=qtg.QKeySequence("Ctrl+Y"),
        )
        edit_menu.addAction(redo_action)

        # セパレータの追加
        edit_menu.addSeparator()

        # [切り取り] アクション
        cut_action = qtg.QAction(
            "切り取り",
            self,
            triggered=self.text_edit.cut,
            shortcut=qtg.QKeySequence("Ctrl+X"),
        )
        edit_menu.addAction(cut_action)

        # [コピー] アクション
        copy_action = qtg.QAction(
            "コピー",
            self,
            triggered=self.text_edit.copy,
            shortcut=qtg.QKeySequence("Ctrl+C"),
        )
        edit_menu.addAction(copy_action)

        # [貼り付け]
        paste_action = qtg.QAction(
            "貼り付け",
            self,
            triggered=self.text_edit.paste,
            shortcut=qtg.QKeySequence("Ctrl+V"),
        )
        edit_menu.addAction(paste_action)
        # ...他アクションも必要に応じて追加

        # ===== [ヘルプ]メニューのアクション追加
        help_action = qtg.QAction(
            self.style().standardIcon(qtw.QStyle.StandardPixmap.SP_DialogHelpButton),
            "ヘルプ",
            self,
            triggered=lambda: self.statusBar().showMessage("ヘルプは作成中です。"),
        )
        help_menu.addAction(help_action)

        # [XXXについて] アクション
        help_menu.addAction("XXXについて", self.show_about_dialog)
        # ...他アクションも必要に応じて追加
        # =============================================

        # ================ ツールバー ==================
        toolbar = self.addToolBar("ツール")
        toolbar.setMovable(True)
        toolbar.setFloatable(False)
        toolbar.setAllowedAreas(
            qtc.Qt.ToolBarArea.TopToolBarArea | qtc.Qt.ToolBarArea.BottomToolBarArea
        )
        toolbar.addAction(open_action)
        toolbar.addAction(save_action)
        toolbar.addAction(help_action)
        # =============================================

        # =============== ステータスバー ===============
        self.statusBar().showMessage("ようこそ!")
        # =============================================

        # 画面表示
        self.show()

    def open_file(self):
        """ファイルを開く"""
        # ファイルダイアログを表示
        filename, _ = qtw.QFileDialog.getOpenFileName(
            self,
            "ファイルを開く",
            qtc.QDir.currentPath(),
            "テキストファイル (*.txt);;すべてのファイル (*)",
            "テキストファイル (*.txt)",
            options=qtw.QFileDialog.Option.DontUseNativeDialog
            | qtw.QFileDialog.Option.DontResolveSymlinks,
        )
        # ファイル読み込み
        if filename:
            try:
                with open(filename, "r") as f:
                    self.text_edit.setText(f.read())
            except Exception as ex:
                selected = qtw.QMessageBox.critical(
                    self,
                    "ファイルオープンエラー",
                    f"ファイルが開けませんでした: {ex}",
                    qtw.QMessageBox.StandardButton.Ok,
                    qtw.QMessageBox.StandardButton.Ok,
                )

    def save_file(self):
        """ファイルを保存する"""
        # ファイルダイアログを表示
        filename, _ = qtw.QFileDialog.getSaveFileName(
            self,
            "ファイルを保存する",
            qtc.QDir.currentPath(),
            "テキストファイル (*.txt);;すべてのファイル (*)",
            "テキストファイル (*.txt)",
            qtw.QFileDialog.Option.DontUseNativeDialog
            | qtw.QFileDialog.Option.DontResolveSymlinks,
        )
        # ファイルの保存
        if filename:
            try:
                with open(filename, "w") as f:
                    f.write(self.text_edit.toPlainText())
            except Exception as ex:
                selected = qtw.QMessageBox.critical(
                    self,
                    "ファイルオープンエラー",
                    f"ファイルが開けませんでした: {ex}",
                    qtw.QMessageBox.StandardButton.Ok,
                    qtw.QMessageBox.StandardButton.Ok,
                )

    def show_about_dialog(self):
        """Aboutダイアログ表示"""
        qtw.QMessageBox.about(self, "プログラム名", "プログラムの説明内容を記載する...")


def main():
    """メイン関数"""
    app = qtw.QApplication(sys.argv)
    mv = MainWindow()
    sys.exit(app.exec())


if __name__ == "__main__":
    main()

詳細説明

上記プログラムの全体構造については、画面開発テンプレート説明で紹介した通りです。以降では、メニューバーやツールバー等、テンプレートの説明部分で説明しきれなかった部分を中心に解説していきます。

中心ウィジェット(central widget)の設定

        # central widgetの設定
        self.text_edit = qtw.QTextEdit()
        self.setCentralWidget(self.text_edit)

QMainWindowを継承したプログラムでは、中心ウィジェット(central widget)を設定します。今回の例は簡易テキストエディタのためQTextEditを設定しています。

中心ウィジェットを設定するには、self.setCentralWidgetを用いて引数に中心ウィジェットを指定します。

今回はQTextEditのみあればよいような簡単なプログラムですが、より複雑なアプリケーションの場合は、QWidgetを中心ウィジェットに設定して、設定したQWidgetの中に様々なコンポーネントを配置したり、レイアウトを設定したりすることで実現することも可能です。

メニューバーの追加

画面上部で「ファイル(F)」となっているような、メニューバーを追加します。メニューを作るときの大きな流れとしては以下のようになります。

  1. メニュー項目の追加
  2. 各メニュー項目のアクションの追加
メニュー項目の追加
        # =============== メニューバー =================
        # ===== メニュー項目の追加
        # [ファイル]メニュー
        file_menu = self.menuBar().addMenu("ファイル(&F)")
        # [編集]メニュー
        edit_menu = self.menuBar().addMenu("編集(&E)")
        # [ヘルプ]メニュー
        help_menu = self.menuBar().addMenu("ヘルプ(&H)")
        # ...他メニューも必要に応じて追加

メニュー項目を追加しているのは上記部分です。QMainWindowを継承したクラス(self)のメニューバーはmenuBar()で取得できます。そこにaddMenuとすることでメニューを追加できます。

なお、addMenuの文字列で「&F」のようにすることキーにAltキーでのショートカットを設定できます。具体的には「Alt」+「指定キー」でメニューを開くことができます。「&」自体を文字列に表示したい場合は「&&」とすることで表示可能です。

なお、上記では[ファイル(F)][編集(E)][ヘルプ(H)]を作っていますが、同じようなコードを記載することで、プログラムに応じて任意のメニューを作成・追加できます。

各メニュー項目のアクションの追加
        # ===== [ファイル]メニューのアクションの追加
        # [ファイルを開く...] アクション
        open_action = qtg.QAction(
            self.style().standardIcon(qtw.QStyle.StandardPixmap.SP_DirOpenIcon),
            "ファイルを開く...",
            self,
            triggered=self.open_file,
            shortcut=qtg.QKeySequence("Ctrl+O"),
        )
        file_menu.addAction(open_action)

各メニューのアクションの追加は上記のような構成になっています。まず、qtg.QActionを生成します。上記の例では以下のような項目を指定しています。

引数内容
QIconアイコンを指定しています。PyQtにはStandardPixmapにいくつかQIconクラスのアイコンがあるのでそれを利用することが可能です。アイコンは省略できます。
textメニューに表示する文字列を指定しています。
parent親としてselfを指定しています。
triggeredクリックされた際に起動するslotを指定しています。
shortcutシュートカットキーを指定しています。qtg.QKeySequenceで「”Ctrl+O”」のように指定することで指定キーで処理を実行できるようになります。

最後に、メニューのインスタンスであるfile_menuにaddActionでアクションを設定することで、メニュー欄に以下のように表示されるようになります。アイコンを設定しているアクションについては、アイコンが表示されていることが分かるかと思います。

QMainWindow メニュー表示

他のメニュー項目のアクション追加も基本的には同じような構成ですので詳細は省略します。クリックされたときの起動するslotやショットカットの設定が異なるだけです。

なお、画面を閉じるだけの[終了]アクションなどであれば、以下のようにシンプルに書くことができます。

        # [終了] アクション
        quit_action = file_menu.addAction("終了", self.close)

[編集(E)][ヘルプ(E)]等についても、同様にメニュー項目のアクションを順番に追加していきます。

ツールバーの追加

上記でメニューバーとアクションを追加する方法を説明しました。それらのアクションを起動するためのツールバーを作成します。

        # ================ ツールバー ==================
        toolbar = self.addToolBar("ツール")
        toolbar.setMovable(True)
        toolbar.setFloatable(False)
        toolbar.setAllowedAreas(
            qtc.Qt.ToolBarArea.TopToolBarArea | qtc.Qt.ToolBarArea.BottomToolBarArea
        )
        toolbar.addAction(open_action)
        toolbar.addAction(save_action)
        toolbar.addAction(help_action)
        # =============================================

self.addToolBarの部分で親画面に「ツール」という名称のツールバーを追加しています。また、ツールバーのメソッドでツールバーの挙動を以下のように指定します。

メソッド名内容
setMovableTrueにするとツールバーを動かすことができるようになります。
setFloatableTrueにするとツールバーを画面外に分離することができます。
setAllowedAreasツールバーが配置できるエリアを指定できます。ORを表す「|」で列挙することで可能なエリアを指定できます。
・TopToolBarArea: 画面上部
・BottomToolBarArea: 画面下部
・LeftToolBarArea: 画面左部
・RightToolBarArea: 画面右部

なお、同じように別のツールバーを追加して、複数ツールバーを作って同時に表示することも可能です。

メニューバーのところで用意した各種アクションをaddActionでツールバーに追加することで、ツールバー上に配置でき、ツールバーで該当するものをクリックするとアクションで設定されているslot処理を実行することができます。

ステータスバーの追加

        # =============== ステータスバー ===============
        self.statusBar().showMessage("ようこそ!")
        # =============================================

ステータスバーはself.statusBar()で取得することができ、showMessageメソッドを使うことで指定した文字列を表示することが可能です。

プログラム実行結果や処理終了通知などを表示したい場合には、適宜ステータスバーに表示することが可能です。

標準ダイアログボックス

アプリケーションでは、各種ダイアログボックスを表示することがあります。メッセージの表示やファイルを開くときのダイアログなどです。これらについてPyQtでは標準で用意されているものがあるため、使い方を紹介します。

QFileDialog

アプリケーションでは、ファイルを開いたり保存したりする際に、ファイル操作のダイアログをよく使用します。PyQtでは、ファイル操作のダイアログとしてQFileDialogが用意されていて簡単に使用することができます。メソッドとしていくつかありますが、上記例では以下のメソッドを使っています。

メソッド返り値説明
getOpenFileNameString開くファイルを選択して、ファイルパスを取得します。
getSaveFileNameString保存ファイルを選択して、ファイルパスを取得します。

上記簡易テキストエディタでは、open_fileメソッドとsave_fileメソッドで以下のように使用しています。(各メソッドのファイルダイアログ表示の部分のみ抜粋しています。)

    def open_file(self):
        """ファイルを開く"""
        # ファイルダイアログを表示
        filename, _ = qtw.QFileDialog.getOpenFileName(
            self,
            "ファイルを開く",
            qtc.QDir.currentPath(),
            "テキストファイル (*.txt);;すべてのファイル (*)",
            "テキストファイル (*.txt)",
            options=qtw.QFileDialog.Option.DontUseNativeDialog
            | qtw.QFileDialog.Option.DontResolveSymlinks,
        )
        # ファイル読み込み
        #(省略)

    def save_file(self):
        """ファイルを保存する"""
        # ファイルダイアログを表示
        filename, _ = qtw.QFileDialog.getSaveFileName(
            self,
            "ファイルを保存する",
            qtc.QDir.currentPath(),
            "テキストファイル (*.txt);;すべてのファイル (*)",
            "テキストファイル (*.txt)",
            qtw.QFileDialog.Option.DontUseNativeDialog
            | qtw.QFileDialog.Option.DontResolveSymlinks,
        )
        # ファイルの保存
        #(省略)

getOpenFileNameやgetSaveFileNameの引数としては、以下のような項目を指定しています。

引数内容
parent親を指定します。上記例では、selfを指定しています。
captionダイアログに表示する文字列を指定します。
directory開くフォルダを指定しています。上記例では、qtc.QDirを使って現在パス(currentPath())を指定しています。
filter拡張子のフィルタ情報を文字列で指定しています。
上記例では、テキストファイル(*.txt)とすべてのファイル(*)としていますが、他の拡張子も必要であれば同じように;;で区切って記載します。
initialFilterデフォルトで表示する拡張子を指定します。
optionダイアログ条件をORを表す(|)で列挙して指定しています。
上記例では、「OS標準のダイアログは使わない」「シンボリックリンクは解決しない」という項目を指定しています。オプションで指定できる項目はこちらを参考にしてください。
QMessageBox

PyQtでは標準的なダイアログボックスとしてQMessabeBoxが用意されていて簡単に使用することができます。メソッドとしては以下のようなものが用意されています。

関数画面タイプ内容
about()モーダレスアプリケーションに関する概要ダイアログを表示する。
aboutQt()モーダレスQtに関する概要ダイアログを表示する。
critical()モーダル致命的(critical)なエラーを通知するためのメッセージダイアログを表示する。
warning()モーダル警告(warning)に通知するためのメッセージダイアログを表示する。
information()モーダル情報(infomation)を通知するためのメッセージダイアログを表示する。
question()モーダルユーザーへの質問用ダイアログを表示する。

上記の簡易テキストエディタの例では、open_fileメソッドとsave_fileメソッドの以下部分で読み込みを失敗した場合のエラー表示として使用しています。(各メソッドのメッセージ表示の関連部分のみ抜粋しています。)

    def open_file(self):
        """ファイルを開く"""
        # ファイルダイアログを表示
        # (省略)

        # ファイル読み込み
        if filename:
            try:
                with open(filename, "r", encoding="utf-8") as f:
                    self.text_edit.setText(f.read())
            except Exception as ex:
                selected = qtw.QMessageBox.critical(
                    self,
                    "ファイルオープンエラー",
                    f"ファイルが開けませんでした: {ex}",
                    qtw.QMessageBox.StandardButton.Ok,
                    qtw.QMessageBox.StandardButton.Ok,
                )


    def save_file(self):
        """ファイル保存"""
        # ファイルダイアログを表示
        # (省略)

        # ファイルの保存
        if filename:
            try:
                with open(filename, "w", encoding="utf-8") as f:
                    f.write(self.text_edit.toPlainText())
            except Exception as ex:
                selected = qtw.QMessageBox.critical(
                    self,
                    "ファイルオープンエラー",
                    f"ファイルが開けませんでした: {ex}",
                    qtw.QMessageBox.StandardButton.Ok,
                    qtw.QMessageBox.StandardButton.Ok
                )

引数としては以下のような項目を指定します。位置引数の順に記載しています。

引数内容
parent親を指定します。上記例では、selfを指定しています。
titleダイアログのタイトル文字列を指定します。
text画面に表示するメッセージを指定します。
buttons表示するボタンを指定します。ボタンはqtw.QMessageBox.StandardButtonで定義されているものが利用できます。複数ボタンを表示したい場合は、「|」で列挙して記述できます。
defaultButtonbuttonsで表示しているボタンでデフォルトで選択状態になり、キーボードでEnterを押したときに有効となるボタンを指定します。

結果としてはselectedに選択されたボタンが返ってくるので、選択されたボタンによって後続の処理の挙動を変えることも可能です。

また、ヘルプメニュー内でプログラムについて表示するAboutダイアログ表示用に作成したslotのメソッド内でも使用しています。

    def show_about_dialog(self):
        """Aboutダイアログ表示"""
        qtw.QMessageBox.about(self, "プログラム名", "プログラムの説明内容を記載する...")

上記のように標準ダイアログをうまく使うと画面開発を効率的に行うことができます。

まとめ

PythonのGUIツールキットであるPyQtで、QMainWindowを継承して画面開発する際の画面テンプレートを紹介しました。

また、実際参考にできる例として簡易テキストエディタの実装例を紹介することで、メニューバーやツールバーの追加方法や標準ダイアログボックスの使い方を解説しました。

PyQtを用いて本格的なメニュー等を含む画面開発を行うための第一歩になるので、これから新規に画面開発をしようとする際のテンプレートとして使用してもらえるとよいかと思います。