コンテンツにスキップ

第 8 章: UI デザインとスタイリング

これまではコードですべての UI を構築してきましたが、複雑な画面になるほど、ウィジェットの配置やプロパティ設定のコードは長く、メンテナンスが困難になります。 この章では、UI デザインをコードから分離する 2 つの強力な手法、Qt DesignerQt Style Sheets (QSS)、そしてアイコンなどのリソース管理について学びます。

Qt Designer の活用

Qt Designer は、ドラッグ&ドロップで UI を視覚的に設計できる GUI ツールです。PySide6 をインストールすると、pyside6-designerというコマンドで起動できます。(仮想環境の場合は、その Scripts フォルダ内にあります)

Designer で作成した UI は.uiという XML 形式のファイルで保存されます。この.uiファイルを Python プログラムで利用するには、主に 2 つの方法があります。

方法 1: 動的読み込み (QUiLoader)

プログラム実行時に.uiファイルを直接読み込む方法です。UI の変更のために Python コードを修正する必要がないため、デザイナーとプログラマーの分業がしやすくなります。

  1. UI の作成: Qt Designer でウィジェットを配置し、objectNameプロパティ(例: submitButton)を設定して、my_form.uiのような名前で保存します。

  2. Python からの読み込みと利用:

    # dynamic_loader_example.py
    import sys
    from PySide6.QtCore import QFile
    from PySide6.QtUiTools import QUiLoader
    from PySide6.QtWidgets import QApplication, QMessageBox
    
    app = QApplication(sys.argv)
    
    # .uiファイルを指定
    ui_file = QFile("my_form.ui")
    ui_file.open(QFile.ReadOnly)
    
    # QUiLoaderで.uiファイルを読み込み、トップレベルウィジェットを取得
    loader = QUiLoader()
    window = loader.load(ui_file)
    ui_file.close()
    
    # objectNameをキーにしてウィジェットにアクセス
    submit_button = window.findChild(QPushButton, "submitButton")
    name_edit = window.findChild(QLineEdit, "nameEdit")
    
    def on_submit():
        name = name_edit.text()
        QMessageBox.information(window, "完了", f"{name}さん、登録しました。")
    
    # シグナルとスロットを接続
    submit_button.clicked.connect(on_submit)
    
    window.show()
    sys.exit(app.exec())
    

方法 2: Python コードへのコンパイル (pyside6-uic)

.uiファイルを事前に Python のクラスコードに変換する方法です。単一の Python ファイルとして完結する利点があります。

  1. UI の作成: 方法 1 と同様に.uiファイルを作成します。

  2. コンパイル: ターミナルでpyside6-uicコマンドを実行します。

    pyside6-uic my_form.ui -o ui_my_form.py
    
  3. 生成されたクラスの利用:

    # compiled_example.py
    import sys
    from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox
    # 生成されたクラスをインポート
    from ui_my_form import Ui_MainWindow
    
    # QMainWindowと生成されたUi_MainWindowの両方を継承
    class MainWindow(QMainWindow, Ui_MainWindow):
        def __init__(self):
            super().__init__()
            # setupUiメソッドを呼び出してUIをセットアップ
            self.setupUi(self)
    
            # ウィジェットにはself.objectNameで直接アクセスできる
            self.submitButton.clicked.connect(self.on_submit)
    
        def on_submit(self):
            name = self.nameEdit.text()
            QMessageBox.information(self, "完了", f"{name}さん、登録しました。")
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        win = MainWindow()
        win.show()
        sys.exit(app.exec())
    

Qt Style Sheets (QSS) によるスタイリング

QSS は、Web の CSS に非常によく似た構文で、Qt ウィジェットの外観を細かくカスタマイズできる仕組みです。

  • 構文: セレクタ { プロパティ: 値; }
  • セレクタ: QPushButton (ウィジェットクラス名), #myButton (objectName), QPushButton:hover (状態)
  • プロパティ: background-color, color, font-size, border, paddingなど

アプリケーション全体にスタイルシートを適用するには、app.setStyleSheet()を使います。

# qss_example.py
# ... (基本的なウィンドウ設定は省略)

# スタイルシートを文字列として定義
style_sheet = """
QPushButton {
    background-color: #4CAF50; /* 緑 */
    color: white;
    border: none;
    padding: 10px 20px;
    font-size: 16px;
}
QPushButton:hover {
    background-color: #45a049; /* 少し暗い緑 */
}
QLineEdit {
    padding: 5px;
    border: 2px solid #ccc;
    border-radius: 5px;
}
"""

app = QApplication(sys.argv)
app.setStyleSheet(style_sheet)

# ... (ウィンドウの表示など)

リソースファイル (.qrc)

アプリケーションで使うアイコンや画像ファイルを、実行ファイルに埋め込むための仕組みです。

  1. resources.qrcファイルの作成: 埋め込みたいファイルをリストアップする XML ファイルを作成します。

    <!DOCTYPE RCC>
    <RCC version="1.0">
    <qresource prefix="/icons">
        <file>open.png</file>
        <file>save.png</file>
    </qresource>
    </RCC>
    
  2. コンパイル: pyside6-rccコマンドで Python ファイルに変換します。

    pyside6-rcc resources.qrc -o resources_rc.py
    
  3. 利用: 生成されたresources_rc.pyをインポートし、:/から始まるパスでリソースにアクセスします。

    import sys
    from PySide6.QtGui import QIcon, QAction
    # 生成されたリソースファイルをインポート
    import resources_rc
    
    # ...
    # QIconのパスにqrcで定義したエイリアスを使う
    open_icon = QIcon(":/icons/open.png")
    open_action = QAction(open_icon, "開く...", self)
    # ...
    

これらのテクニックを組み合わせることで、機能とデザインが分離された、メンテナンスしやすく、かつ見た目も美しいアプリケーションを効率的に開発することができます。