mcpField
P
pyqt6-ui-development-rules

pyqt6-ui-development-rules

github.com/oimiragieo開発441.1k 回インストール17 週間前に更新
リポジトリ

pyqt6-ui-development-rules について

PyQt6 のデスクトップ GUI を構築、改修、デバッグする開発者向けの開発スキルです。MVC 分離、スレッド処理、テーマ設定、クロスプラットフォームのレイアウトを扱います。

主な機能

  1. 01MVC 分離とシグナル・スロット通信
  2. 02アプリケーション単位の QSS テーマ設定
  3. 03QThread とスレッドプールによるバックグラウンド処理
  4. 04レイアウトマネージャーによるレスポンシブ設計
  5. 05クロスプラットフォームの DPI とアクセシビリティ対応

活用シーン

  1. 01新しい PyQt6 デスクトップアプリの構築
  2. 02既存の PyQt または PySide コードの改修
  3. 03画面のフリーズや応答停止の調査
  4. 04カスタムウィジェットや複雑なレイアウトの実装

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/oimiragieo/agent-studio --skill pyqt6-ui-development-rules

インストール後、Claude Code で/pyqt6-ui-development-rulesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

commands/
pyqt6-ui-development-rules.md
hooks/
post-execute.cjs
pre-execute.cjs
references/
research-requirements.md
rules/
pyqt6-ui-development-rules.md
schemas/
input.schema.json
output.schema.json
scripts/
main.cjs
templates/
implementation-template.md

詳細

PyQt6 UI 開発ルールスキル

MVC の分離、シグナル/スロットアーキテクチャ、QSS によるテーマ設定、スレッドによる並行処理、クロスプラットフォームのレンダリングに関するベストプラクティスを徹底する、PyQt6 デスクトップ GUI 開発のスペシャリストです。応答性、アクセシビリティ、視覚的な一貫性を備えたデスクトップアプリケーションを実現します。 - MVC を分離した PyQt6 アプリケーションアーキテクチャを設計する - UI とビジネスロジック間のシグナル/スロットによる通信パターンを実装する - ダークモード/ライトモードに対応する、アプリケーションレベルの QSS テーマ設定を構成する - QThread、QRunnable、QThreadPool を使用してバックグラウンド処理を管理する - QVBoxLayout、QHBoxLayout、QGridLayout、QFormLayout を使用して応答性の高いレイアウトを構築する - 適切な paintEvent 処理を備えたカスタム QWidget サブクラスを実装する - クロスプラットフォームの DPI 対応レンダリングを設定する - アクセシビリティ機能(スクリーンリーダー対応、キーボードナビゲーション)を構成する

概要

このスキルでは、実用レベルの PyQt6 デスクトップアプリケーションを構築するためのルールを徹底します。中心となる原則は、シグナル/スロットによる厳格な MVC の分離、UI スレッドを決してブロックしないこと、QSS による一元的なテーマ設定、レイアウトマネージャーを活用した応答性の高い設計です。これらのルールにより、UI のフリーズ、テスト困難な結合、プラットフォーム固有のレンダリングバグなど、PyQt6 でよく発生する問題を防ぎます。

使用する場面

  • 新しい PyQt6 デスクトップアプリケーションを構築するとき
  • 既存の PyQt/PySide コードを PyQt6 にリファクタリングするとき
  • Qt UI のフリーズや応答停止をデバッグするとき
  • カスタムウィジェットや複雑なレイアウトを実装するとき
  • クロスプラットフォームのデスクトップアプリケーションのビルドを設定するとき

絶対に守るべきルール

  1. 必ず UI からロジックへの通信には Qt のシグナル/スロット機構を使用してください。UI 層とビジネスロジック層の間でメソッドを直接呼び出すと、MVC の分離が損なわれ、テスト困難な結合が生じます。
  2. 決して メイン UI スレッドで時間のかかる処理を実行しないでください。Qt のイベントループをブロックすると、インターフェースが応答しなくなり、OS の「応答なし」ダイアログが表示されます。
  3. 必ず QSS スタイルシートはウィジェットごとではなく、QApplication レベルで適用してください。ウィジェットごとのインラインスタイルは、テーマに一貫性がなく、保守困難なスタイル設定の乱立を招きます。
  4. 決して ウィジェットのレイアウトに絶対的なピクセル座標を使用しないでください。DPI 対応およびクロスプラットフォームのレンダリングを実現するため、Qt のレイアウトマネージャー(QVBoxLayout、QHBoxLayout、QGridLayout)を使用してください。
  5. 必ず リリース前に対象となるすべてのプラットフォームで UI をテストしてください。PyQt6 のレンダリング、フォントの拡大縮小、ウィジェットのサイズは、Windows、macOS、Linux で異なります。

アンチパターン

アンチパターン失敗する理由正しい方法
UI スロットからビジネスロジックを直接呼び出すUI とロジックが密結合になり、テストが不可能になり、MVC アーキテクチャが崩れますUI からシグナルを発行し、スロット経由でコントローラー/サービスのメソッドに接続します
メインスレッドでネットワークやファイルの I/O を実行するQt のイベントループをブロックし、処理が完了するまで UI がフリーズしますバックグラウンド処理には QThread、QRunnable、または qasync を使った asyncio を使用します
ピクセルサイズや位置をハードコードする高 DPI ディスプレイや OS ごとに異なる DPI スケーリング設定でレイアウトが崩れますレイアウトマネージャーとサイズポリシーを使用し、DPI に応じたサイズ設定には logicalDpiX() を使います
個々のウィジェットにスタイルをインラインで設定する見た目に一貫性がなくなり、テーマ設定やメンテナンスが非常に困難になりますQApplication レベルで単一の QSS スタイルシートを定義し、オブジェクト名/クラスを使用します
クロスプラットフォームの描画の違いを無視するウィジェットのサイズ、フォント、余白は Windows/macOS/Linux 間で大きく異なります対象となるすべてのプラットフォームでテストし、描画に違いがある場合はプラットフォーム条件付きのロジックを使用します

ワークフロー

ステップ 1:アプリケーションアーキテクチャ(MVC)
# model.py -- Business logic, no Qt dependencies
class DataModel:
    def __init__(self):
        self._items = []

    def add_item(self, item: str) -> bool:
        if item and item not in self._items:
            self._items.append(item)
            return True
        return False

# controller.py -- Mediates between Model and View
from PyQt6.QtCore import QObject, pyqtSignal

class Controller(QObject):
    items_changed = pyqtSignal(list)
    error_occurred = pyqtSignal(str)

    def __init__(self, model: DataModel):
        super().__init__()
        self._model = model

    def add_item(self, item: str) -> None:
        if self._model.add_item(item):
            self.items_changed.emit(self._model._items.copy())
        else:
            self.error_occurred.emit(f"Could not add: {item}")
ステップ 2:シグナル/スロットの接続
# view.py -- UI only, connects via signals/slots
from PyQt6.QtWidgets import QMainWindow, QVBoxLayout, QWidget, QLineEdit, QPushButton, QListWidget

class MainView(QMainWindow):
    def __init__(self, controller: Controller):
        super().__init__()
        self._controller = controller

        # Wire signals to slots
        self._controller.items_changed.connect(self._on_items_changed)
        self._controller.error_occurred.connect(self._on_error)

        # UI emits to controller -- never calls model directly
        self._add_btn.clicked.connect(lambda: self._controller.add_item(self._input.text()))

    def _on_items_changed(self, items: list) -> None:
        self._list.clear()
        self._list.addItems(items)
ステップ 3:バックグラウンド処理
from PyQt6.QtCore import QThread, pyqtSignal

class WorkerThread(QThread):
    progress = pyqtSignal(int)
    finished_with_result = pyqtSignal(object)
    error = pyqtSignal(str)

    def __init__(self, task_fn, parent=None):
        super().__init__(parent)
        self._task_fn = task_fn

    def run(self):
        try:
            result = self._task_fn(self.progress.emit)
            self.finished_with_result.emit(result)
        except Exception as e:
            self.error.emit(str(e))
ステップ 4:QSS によるテーマ設定
# Apply at QApplication level
app = QApplication(sys.argv)
app.setStyleSheet(Path("styles/dark-theme.qss").read_text())

# QSS file
"""
QMainWindow {
    background-color: #2b2b2b;
    color: #e0e0e0;
}
QPushButton {
    background-color: #3c3f41;
    border: 1px solid #555;
    border-radius: 4px;
    padding: 6px 16px;
    color: #e0e0e0;
}
QPushButton:hover {
    background-color: #4c5052;
}
"""
ステップ 5:レイアウト管理
# Use layout managers -- never setGeometry() or move()
layout = QVBoxLayout()
layout.addWidget(self._toolbar)
layout.addWidget(self._content, stretch=1)  # stretch fills available space
layout.addWidget(self._status_bar)

# For responsive grids
grid = QGridLayout()
grid.addWidget(label, 0, 0)
grid.addWidget(input_field, 0, 1)
grid.setColumnStretch(1, 1)  # input stretches, label stays fixed

関連スキル

スキル関連性
modern-pythonuv、ruff、ty、pytest を使ったプロジェクトのセットアップ
python-backend-expertデスクトップアプリのバックエンド向けバックエンドサービスのパターン
tddQt ウィジェットのテストにおけるテスト駆動開発
accessibilityデスクトップアプリに適用できるアクセシビリティ監査のパターン

メモリプロトコル(必須)

開始前:

過去の PyQt6 のパターンやプラットフォーム固有の回避策について、.claude/context/memory/learnings.md を読みます。

完了後: プラットフォーム固有の描画上の問題、シグナル/スロットのパターン、または QThread の注意点があれば、.claude/context/memory/learnings.md に記録します。

中断されることを想定してください。コンテキストがリセットされる場合があります。メモリに記録されていなければ、起きていないのと同じです。

コメント