コンテンツにスキップ

第 4 章: 主要なウィジェット

アプリケーションの骨格(QMainWindow)と動作の仕組み(シグナルとスロット)を学びました。 この章では、ユーザーインターフェースを構成する具体的な「部品」であるウィジェットについて、その役割と使い方を学びます。

レイアウト管理の重要性

個々のウィジェットを学ぶ前に、レイアウトの重要性を再確認します。 ウィジェットをウィンドウに配置する際、move(x, y)のように座標を直接指定する方法(絶対配置)もありますが、ウィンドウサイズが変わるとレイアウトが崩れてしまいます。

QVBoxLayout(垂直)、QHBoxLayout(水平)、QGridLayout(グリッド)といったレイアウトクラスを使うことで、ウィンドウサイズが変更されてもウィジェットの配置が自動的に調整される、柔軟でプロフェッショナルな UI を構築できます。

主要なウィジェット紹介

ここでは、多くのアプリケーションで共通して使われる基本的なウィジェットを紹介します。

QLabel: ラベル

テキストや画像を表示するためのウィジェットです。 ユーザーとのインタラクション機能はありません。

  • 主なメソッド: setText(str), setPixmap(QPixmap)
  • 主なシグナル: なし(表示専用のため)
label = QLabel("これは読み取り専用のテキストです")
# 画像を表示する場合
# from PySide6.QtGui import QPixmap
# pixmap = QPixmap("path/to/image.png")
# label.setPixmap(pixmap)

QPushButton: プッシュボタン

ユーザーがクリックすることで、特定のアクションを開始するためのボタンです。

  • 主なメソッド: setText(str), setIcon(QIcon)
  • 主なシグナル: clicked()
button = QPushButton("実行")
button.clicked.connect(self.run_process) # run_processはスロット

QLineEdit: 1 行テキスト入力

ユーザー名や検索語など、1 行の短いテキストを入力させるためのウィジェットです。

  • 主なメソッド: text() (テキスト取得), setText(str) (テキスト設定), setPlaceholderText(str) (プレースホルダー設定)
  • 主なシグナル: textChanged(str) (テキストが 1 文字でも変わるたび), returnPressed() (Enter キーが押されたとき)
line_edit = QLineEdit()
line_edit.setPlaceholderText("名前を入力してください")
print(line_edit.text()) # 入力されたテキストを取得

QCheckBox: チェックボックス

オン/オフの状態を切り替えることができるチェックボックスです。 複数の選択肢を独立して選ばせたい場合に使用します。

  • 主なメソッド: isChecked() (状態取得), setText(str)
  • 主なシグナル: stateChanged(int) (状態が変わったとき。引数で状態 Qt.CheckState を受け取れる)
check = QCheckBox("規約に同意する")
if check.isChecked():
    print("同意済み")

QRadioButton: ラジオボタン

複数の選択肢の中から、一つだけを選ばせたい場合に使用します。 通常、複数のラジオボタンをレイアウトやQButtonGroupでグループ化して使います。

  • 主なメソッド: isChecked() (状態取得), setText(str)
  • 主なシグナル: toggled(bool) (選択状態が切り替わったとき)
rb1 = QRadioButton("選択肢A")
rb2 = QRadioButton("選択肢B")
rb1.setChecked(True) # 初期状態で選択

QComboBox: コンボボックス

ドロップダウンリストから項目を選択させるウィジェットです。選択肢が多い場合にスペースを節約できます。

  • 主なメソッド: currentText() (選択中テキスト取得), currentIndex() (選択中インデックス取得), addItems(list[str]) (項目追加)
  • 主なシグナル: currentTextChanged(str) (選択項目が変わったとき)
combo = QComboBox()
combo.addItems(["Windows", "macOS", "Linux"])
combo.currentTextChanged.connect(self.on_os_changed)

総合実践:簡単な登録フォームの作成

これらのウィジェットとQGridLayoutを使って、簡単なユーザー登録フォームを作成してみましょう。

# simple_form.py
import sys
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QGridLayout,
    QLabel, QLineEdit, QPushButton, QComboBox, QCheckBox
)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("登録フォーム")

        # --- ウィジェットの作成 ---
        self.name_label = QLabel("名前:")
        self.name_edit = QLineEdit()
        self.os_label = QLabel("OS:")
        self.os_combo = QComboBox()
        self.os_combo.addItems(["Windows", "macOS", "Linux"])
        self.agree_check = QCheckBox("利用規約に同意する")
        self.submit_button = QPushButton("登録")

        # --- レイアウトの設定 (グリッドレイアウト) ---
        layout = QGridLayout()
        layout.addWidget(self.name_label, 0, 0) # 0行0列
        layout.addWidget(self.name_edit, 0, 1)  # 0行1列
        layout.addWidget(self.os_label, 1, 0)   # 1行0列
        layout.addWidget(self.os_combo, 1, 1)   # 1行1列
        layout.addWidget(self.agree_check, 2, 0, 1, 2) # 2行0列から1行分、2列分を占有
        layout.addWidget(self.submit_button, 3, 0, 1, 2) # 3行0列から1行分、2列分を占有

        # 中央ウィジェットの設定
        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

        # --- シグナルとスロットの接続 ---
        self.submit_button.clicked.connect(self.on_submit)
        self.agree_check.stateChanged.connect(self.on_agree_changed)

        # --- 初期状態の設定 ---
        self.submit_button.setEnabled(False) # 最初は登録ボタンを無効化

    def on_agree_changed(self, state):
        # チェックボックスの状態に応じて登録ボタンの有効/無効を切り替え
        self.submit_button.setEnabled(state == 2) # Qt.CheckState.Checked == 2

    def on_submit(self):
        name = self.name_edit.text()
        os = self.os_combo.currentText()
        print(f"登録情報:\n  名前: {name}\n  OS: {os}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_win = MainWindow()
    main_win.show()
    sys.exit(app.exec())

この例では、QGridLayoutを使ってフォームらしい見た目を実現し、チェックボックスのシグナル(stateChanged)を使ってボタンの有効/無効を切り替える、より実践的なインタラクションを実装しています。