第 2 章: GUI アプリケーションの基本構造
第 1 章では、最小限のコードでウィンドウを表示しました。この章では、そのコードの各部分がどのような役割を担っているのかを詳しく解説し、より構造化されたアプリケーションの骨格を学びます。
# main.py (第1章のコード再掲)
import sys
from PySide6.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('最初のウィンドウ')
window.resize(300, 200)
window.show()
sys.exit(app.exec())
QApplication: すべてのアプリケーションの心臓部
app = QApplication(sys.argv)
すべての PySide6 アプリケーションには、ただ一つのQApplicationインスタンスが必須です。これはアプリケーション全体の管理オブジェクトであり、以下の役割を担います。
- 初期化と終了処理: GUI の初期化、イベントループの管理、リソースの解放など、アプリケーションのライフサイクル全体を管理します。
- イベント処理: ユーザーからの入力(マウスクリック、キーボード入力など)やシステムからの通知(ウィンドウの再描画要求など)といった「イベント」を受け取り、適切なウィジェットに伝達します。
- コマンドライン引数の処理:
sys.argvを渡すことで、Qt 自身が使用する標準的なコマンドライン引数(例:-style fusionなど)を解釈させることができます。
QWidgetとQMainWindow: ウィンドウの基礎
window = QWidget()
PySide6 では、画面に表示されるすべての要素(ウィンドウ、ボタン、ラベルなど)をウィジェットと呼びます。QWidgetクラスは、これらすべてのウィジェットの基底クラスです。
第 1 章ではQWidgetを直接使ってウィンドウを作成しましたが、これは最もシンプルな「空のキャンバス」のようなものです。一般的なデスクトップアプリケーションを構築する際には、より高機能なQMainWindowを使用するのが一般的です。
| クラス | 説明 |
|---|---|
QWidget |
すべての UI コンポーネントの基本。単純なウィンドウや、他のウィジェットのコンテナとして使用。 |
QMainWindow |
メインウィンドウ用のクラス。メニューバー、ツールバー、ステータスバー、中央ウィジェットなどを配置するための専用領域が予め用意されている。 |
ほとんどのアプリケーション開発では、QMainWindowを継承したカスタムクラスを作成し、それをメインウィンドウとして使用します。
イベントループとは何か? (app.exec())
sys.exit(app.exec())
この一行は、GUI アプリケーションの動作の根幹をなす部分です。
app.exec(): イベントループを開始します。これは、アプリケーションが終了するまで無限に回り続けるループです。- ループの中で、アプリケーションはユーザーからの操作(イベント)を待ち続けます。
- イベントが発生すると、
QApplicationはそれを検知し、適切なウィジェットに処理を依頼します。 - イベントの処理が終わると、再び待機状態に戻ります。
sys.exit(...): イベントループが終了したとき(例: ユーザーがウィンドウを閉じたとき)、app.exec()は終了コード(通常は 0)を返します。sys.exit()でラップすることで、アプリケーションのプロセスを安全かつクリーンに終了させることができます。
コマンドラインツールが上から下に処理を実行して終了するのとは対照的に、GUI アプリケーションはイベントループによって「生き続け」、ユーザーの操作に反応するという点が本質的な違いです。
クラスを使った構造化
ここまでのコードはシンプルですが、機能が増えるにつれて管理が難しくなります。オブジェクト指向の原則に従い、メインウィンドウをクラスとして定義するのが一般的で、より拡張性の高いアプローチです。
以下は、第 1 章のコードをQMainWindowを継承したクラスで書き直した例です。
# main_structured.py
import sys
from PySide6.QtWidgets import QApplication, QMainWindow
# QMainWindowを継承してメインウィンドウのクラスを定義
class MainWindow(QMainWindow):
def __init__(self):
# 親クラス(QMainWindow)のコンストラクタを呼び出す
super().__init__()
# ウィンドウの初期設定
self.setWindowTitle("構造化されたアプリケーション")
self.resize(400, 300)
# --- ここからがアプリケーションの実行部分 ---
if __name__ == "__main__":
app = QApplication(sys.argv)
# MainWindowクラスのインスタンスを作成
main_win = MainWindow()
main_win.show()
sys.exit(app.exec())
このようにクラスとしてまとめておくことで、ウィンドウに関連する機能(メソッド)やデータ(インスタンス変数)を一つの場所にカプセル化でき、コードの見通しが格段に良くなります。今後のガイドでは、基本的にこのクラスベースの構造を採用します。
次の章では、いよいよ GUI アプリケーションのインタラクティブ性を実現する最重要機能、「シグナルとスロット」について学びます。