本文へ移動
cccskills
無料GitHub で公開

pyqt

Use when building cross-platform desktop apps with PyQt6 or PySide6 - hub for installation, project structure, signals and slots basics, and pointers to widgets, styling, dialogs, threading, and testing sub-skills

インストール方法を見る

含まれるファイル(18)

  • SKILL.md13.8 KB
  • core/SKILL.md10.5 KB
  • dialogs/SKILL.md12.4 KB
  • multimedia/references/codecs-platforms.md7.8 KB
  • multimedia/references/media-pipeline.md17.0 KB
  • multimedia/SKILL.md9.4 KB
  • styling/references/dark-theme.md4.0 KB
  • styling/SKILL.md11.4 KB
  • testing/SKILL.md17.7 KB
  • threading/references/advanced-safety.md5.4 KB
  • threading/references/lifecycle-cleanup.md3.2 KB
  • threading/references/pool-patterns.md8.0 KB
  • threading/references/qt-concurrent.md4.3 KB
  • threading/references/testing.md8.5 KB
  • threading/SKILL.md12.7 KB
  • widgets/references/event-handling.md2.3 KB
  • widgets/references/item-views-layouts.md4.2 KB
  • widgets/SKILL.md9.7 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

PyQt/PySide Development

PyQt and PySide are Python bindings for the Qt application framework for building cross-platform desktop applications.

Sub-Skills

For detailed information, see the specialized sub-skills:

SkillDescriptionPath
pyqt-coreSignals, slots, timers, settings, file I/Ocore/SKILL.md
pyqt-widgetsAll widgets and layoutswidgets/SKILL.md
pyqt-threadingQThread, thread pools, concurrencythreading/SKILL.md
pyqt-dialogsStandard and custom dialogsdialogs/SKILL.md
pyqt-testingpytest-qt testing patternstesting/SKILL.md
pyqt-stylingQSS styling and themesstyling/SKILL.md
pyqt-multimediaAudio, video, camera, recordingmultimedia/SKILL.md

Architecture Decision: MVC vs MVVM in Qt

Qt supports multiple architectural patterns. Choose based on your data-display complexity.

MVC (Model-View-Controller)

When to use: Simple data display with inline editing, standard item views.

  • Model: QAbstractItemModel subclass owns the data
  • View: QTableView, QTreeView, QListView displays data
  • Controller: Built into the view (header clicks, selection handling)
  • Validation: In the model's setData() method
  • Signals: Model emits dataChanged(), rowsInserted() to notify views
# Model owns data and validation
class DataModel(QAbstractTableModel):
    def setData(self, index, value, role):
        if not self._validate(value):
            return False
        # update and emit dataChanged

MVVM (Model-View-ViewModel)

When to use: Same data displayed in multiple widgets with different formatting, complex UI state.

  • Model: Data source (database, API, file)
  • ViewModel: Transforms model data for display, owns UI state
  • View: PyQt widgets bound to ViewModel via signals
  • Validation: In ViewModel, before updating Model
  • Signals: ViewModel exposes Property signals; View connects to them
# ViewModel transforms data for display
class UserViewModel(QObject):
    display_name = Property(str, _display_name_changed)
    
    def __init__(self, user_model):
        self._user = user_model
        self._user.nameChanged.connect(self._on_model_changed)

Practical Test: Where Does Formatting Belong?

If the same data is displayed in two widgets with different formatting, the formatting belongs in a view-model/delegate, not duplicated in both widgets.

Bad:

# Widget A
label.setText(f"{value:.2f} €")
# Widget B  
label.setText(f"€ {value:,.2f}")

Good:

# ViewModel provides formatted strings
class PriceViewModel(QObject):
    display_eu = Property(str)
    display_us = Property(str)
    
    def set_price(self, value):
        self._price = value
        self.display_eu_changed.emit()
        self.display_us_changed.emit()

Signals/Slots: When Is That Enough?

Signals and slots alone are sufficient when:

  • One widget displays one data source
  • No complex derived state (e.g., "show X only if Y and Z")
  • Validation can live in the model's setData()
  • You don't need to test UI logic without the widgets

Add a ViewModel layer when:

  • Multiple views need the same data in different formats
  • UI state (enabled/disabled, visibility) depends on complex conditions
  • You want to test display logic without instantiating widgets

Where Does This Belong?

Use this routing to load only the sub-skill you need:

IntentLoad This Sub-Skill
Signal declaration, slot decorators, pyqtSignal/Signal, typed signals, connect(), disconnect(), signal chainspyqt/core
Widget composition (building custom widgets from multiple widgets), item views (QTableView, QTreeView), delegates (QItemDelegate), event filterspyqt/widgets
QThread worker-object pattern, QThreadPool/QRunnable, QExecutor, thread safety, cancellation, blocking operationspyqt/threading
Standard dialogs (QFileDialog, QMessageBox, QInputDialog, QColorDialog, QFontDialog), custom QDialog patterns, modal vs modelesspyqt/dialogs
pytest-qt fixture (qtbot), waitSignal, mouse/keyboard simulation, dialog testing, model/view testingpyqt/testing
QSS syntax, pseudo-states (:hover, :pressed), widget-specific styles, theming, platform differencespyqt/styling

What Does NOT Belong in the Hub

  • Signals/slots basics → pyqt/core (this hub only routes)
  • Widget lists → pyqt/widgets (this hub only routes)
  • QSS syntax and examples → pyqt/styling (this hub only routes)
  • Layout code snippets → pyqt/widgets (this hub only routes)

Deep Dives

Load these sub-skills for specialized topics:

  • Signals/slots deep dive → pyqt/core - Signal declaration, slot decorators, connections, typed signals
  • Widgets, layouts, item views, event handling → pyqt/widgets - Display/input/container widgets, QVBoxLayout/QHBoxLayout/QGridLayout, event filters, shortcuts
  • QSS styling and dark theme → pyqt/styling - QSS syntax, pseudo-states, widget-specific styles, property-based styling
  • Dialogs → pyqt/dialogs - Standard dialogs (QFileDialog, QMessageBox, QInputDialog), custom QDialog patterns, modal/modeless
  • Threading patterns → pyqt/threading - QThread worker-object pattern, QThreadPool/QRunnable, thread safety, cancellation
  • pytest-qt testing → pyqt/testing - qtbot fixture, waitSignal, mouse/keyboard simulation, dialog testing, model/view testing

PyQt vs PySide Comparison

FeaturePyQt5PyQt6PySide6
LicenseGPLGPLLGPL
Qt VersionQt 5Qt 6Qt 6
MaintainedSecurity onlyActiveActive
Signal SyntaxpyqtSignalpyqtSignalSignal
Slot SyntaxpyqtSlotpyqtSlotSlot
Property SyntaxpyqtPropertypyqtPropertyProperty
Commercial UseRequires licenseRequires licenseFree
QML RegistrationqmlRegisterType()qmlRegisterType()@QmlElement

When to Use Each

  • PySide6: Recommended for most projects (LGPL, official Qt Company support)
  • PyQt6: If you need GPL compatibility or existing PyQt codebase
  • PyQt5: Legacy projects only (security fixes only)

Installation

PySide6 (Recommended)

pip install PySide6

PyQt6

pip install PyQt6

PyQt5 (Legacy)

pip install PyQt5

Additional Dependencies

# System packages (Ubuntu/Debian)
sudo apt install libgl1-mesa-glx libglib2.0-0

# System packages (Fedora)
sudo dnf install mesa-libGL glib2

# System packages (Arch)
sudo pacman -S mesa glib2

Basic Application

#!/usr/bin/env python3
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel
from PySide6.QtCore import Qt

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("My Application")
        self.setGeometry(100, 100, 800, 600)
        
        label = QLabel("Hello, Qt!")
        label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.setCentralWidget(label)

def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

if __name__ == "__main__":
    main()

Recommended Project Structure

my_app/
├── src/
│   ├── __init__.py
│   ├── main.py
│   ├── main_window.py
│   ├── widgets/
│   │   ├── __init__.py
│   │   └── custom_widget.py
│   ├── models/
│   │   └── data_model.py
│   ├── resources/
│   │   ├── icons/
│   │   └── styles/
│   │       └── style.qss
│   └── utils/
│       └── helpers.py
├── tests/
│   └── test_main.py
├── requirements.txt
└── pyproject.toml

Quick Reference

Core Imports

from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QPushButton, QLineEdit, QTextEdit, QComboBox, QSpinBox, QCheckBox, QSlider, QProgressBar, QGroupBox, QTabWidget, QStackedWidget, QSplitter, QListWidget, QTreeWidget, QTableWidget, QScrollArea, QToolBar, QStatusBar
from PySide6.QtCore import Qt, QObject, QTimer, QThread, Signal, Slot, Property, QSize, QPoint, QRect, QSettings, QFile, QDir, QUrl, QMimeData, QDateTime
from PySide6.QtGui import QIcon, QPixmap, QImage, QPainter, QPen, QBrush, QColor, QFont, QCursor, QKeySequence, QShortcut

Common Properties

widget.setEnabled(True)  # Enable/disable
widget.setVisible(False)  # Visibility
widget.setToolTip("Help")  # Tooltip
widget.setObjectName("myButton")  # QSS selector
widget.setProperty("primary", True)  # Custom property

Packaging & Distribution

PyInstaller

# Install
pip install pyinstaller

# Single executable
pyinstaller --onefile --windowed app.py

# With icon and data files
pyinstaller --onefile --windowed --icon=app.ico --add-data "resources:resources" app.py

PyInstaller Spec File

# app.spec
a = Analysis(
    ['app.py'],
    pathex=[],
    binaries=[],
    datas=[('resources', 'resources')],
    hiddenimports=[],
    hookspath=[],
    runtime_hooks=[],
    excludes=[],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=None,
    noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data)
exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='MyApp',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    console=False,
    icon='app.ico',
)

cx_Freeze

# setup.py
from cx_Freeze import setup, Executable

build_options = {
    'packages': ['PySide6'],
    'excludes': ['tkinter'],
    'include_files': [('resources', 'resources')]
}

setup(
    name='MyApp',
    version='1.0',
    description='My Qt Application',
    options={'build_exe': build_options},
    executables=[Executable('app.py', base='Win32GUI', icon='app.ico')]
)

Build Commands

# PyInstaller
pyinstaller --clean app.spec

# cx_Freeze
python setup.py build

# Create distribution
pyinstaller --clean --distpath dist app.spec

Distribution Checklist

  • Test on clean VM (no Python installed)
  • Verify all assets bundled (icons, QSS, translations)
  • Check executable size (strip debug symbols if needed)
  • Test on target OS versions
  • Sign executable (Windows/macOS)
  • Create installer (optional: NSIS, Inno Setup, dmgbuild)

Best Practices

Architecture

  1. Separate UI from business logic - Use MVC or MVVM patterns
  2. Use dependency injection - Pass dependencies to constructors
  3. Keep widgets stateless - Store state in models, not widgets
  4. Use signals for decoupling - Components communicate via signals
  5. Lazy load heavy resources - Load images/data on demand

Performance

  1. Avoid blocking the main thread - Use workers for long operations
  2. Use view delegates for complex item rendering - Don't subclass QItemDelegate unnecessarily
  3. Batch UI updates - Block signals during bulk changes
  4. Reuse widgets - Pool frequently created widgets
  5. Profile before optimizing - Use python -m cProfile

Memory Management

  1. Use parent-child relationships - Qt auto-cleans children
  2. Call deleteLater() for dynamic widgets - Don't use del directly
  3. Break signal/slot connections - Disconnect before deleting
  4. Avoid circular references - Use weak references where needed
  5. Monitor with tracemalloc - Find memory leaks

Code Organization

  1. One class per file - Keep modules focused
  2. Group related widgets - Custom widgets in separate modules
  3. Centralize constants - Use enums for fixed values
  4. Use type hints - Helps with IDE support and debugging
  5. Document public APIs - Docstrings for methods and classes

Troubleshooting

IssueCauseSolution
UI freezesBlocking operation in main threadMove to worker thread
Crashes on widget accessAccessing UI from worker threadUse signals instead
Memory leaksObjects not cleaned upUse parent-child relationships, deleteLater()
QSS not applyingWrong selector or syntaxCheck widget objectName, use style().polish()
Signals not firingWrong connection typeVerify signal declaration, check thread affinity
High CPU usageTight loop in main threadUse timers or workers
Window not showingMissing show() callCall window.show() before app.exec()
Icons not loadingWrong path or formatUse QResource for bundled assets

Debugging Tips

# Enable Qt logging
import logging
logging.basicConfig(level=logging.DEBUG)

# Check for unhandled exceptions
import sys
sys.excepthook = lambda exc: print(f"Unhandled: {exc}")

# Print widget hierarchy
print(window.findChildren(QWidget))

# Check signal connections
print(button.receivers(button.clicked))

# Dump QSS errors
app.setStyleSheet("INVALID {")  # Will print parse errors

References

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

aiohttp

無料

Use when building Python async HTTP services or clients with aiohttp - web server routing, middleware, WebSocket, SSE, streaming, client sessions, pytest-aiohttp testing, or troubleshooting SSL and timeout issues

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

ast-grep

無料

Use when doing structural code search and rewriting - ast-grep linting, refactoring, multi-language patterns

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

Use when building GBA games with the BPCore Lua engine - entity, sprite and tilemap functions, SRAM save and load, link cable multiplayer protocol, camera and scrolling, or optimization patterns

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

celery

無料

Use when running background tasks with Celery - worker and broker configuration (Redis, RabbitMQ), task routing by name vs queue, chains/groups/chords, retry patterns (autoretry_for, retry_backoff), acks_late semantics, failure detection, and monitoring with Flower

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

django

無料

Use when building Django applications - security hardening, authentication and permissions, ORM optimization, PostgreSQL features, Django 6.0, migrations, testing, and ecosystem libraries

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

Use when customizing Django Admin - save_formset, get_search_results, formsets, queryset optimization, db_index, custom URLs

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

CodeAtCode のスキルをすべて見る

このスキルの問題を報告する