\ 迷ったらまずTechAcademyの無料カウンセリング! /
PySide超入門【第19回 | 応用編】カスタムウィジェットの作り方!QWidgetの継承と描画

GUIアプリケーションを開発していると、標準のウィジェットでは表現しきれない独自の見た目や動作が必要になることがあります。そのような場合に役立つのがカスタムウィジェットの作成です。
本記事では、QWidget
を継承してカスタム描画を行う方法を中心に、基本構造から便利なプロパティ・メソッド、描画イベントの実践例まで解説します。
QWidgetとは?
QWidget
は、PySide6におけるすべてのGUI部品(ボタン、ラベル、テキストボックスなど)の「土台」となる基本クラスです。
PySide6(Qt)では、すべてのUI要素がこのQWidget
をベースにして作られています。
つまり、自分で「オリジナルのウィジェット(部品)」を作りたいときも、QWidget
を継承することで、独自の機能や見た目を持った部品を作成できます。
特に描画処理(カスタム描画)を行いたい場合には、QWidget
を継承し、paintEvent()
という関数を使って、自分だけのUIを描き出すことができます。
基本コード
以下は、QWidget
を継承してカスタムウィジェットを作成する最小構成のコードです
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QColor
import sys
class CustomWidget(QWidget):
# QWidgetをクラス継承
def __init__(self):
super().__init__()
self.setWindowTitle("カスタムウィジェットの例")
self.resize(300, 200)
def paintEvent(self, event):
# paintEvent() をオーバーライド
painter = QPainter(self)
painter.setBrush(QColor("skyblue"))
painter.drawRect(50, 50, 200, 100)
app = QApplication(sys.argv)
window = CustomWidget()
window.show()
sys.exit(app.exec())
行 | 説明 |
---|---|
CustomWidget(QWidget) | QWidget を継承して自作ウィジェットを定義します。 |
self.setWindowTitle() | ウィンドウのタイトルを設定します。 |
self.resize() | ウィンドウのサイズを幅300px × 高さ200pxに設定します。 |
widget.show() | ウィジェットを画面に表示します。 |
app.exec() | アプリケーションのイベントループを開始します。ウィンドウが閉じられるまで実行され続けます。 |

主なプロパティとメソッド一覧(全解説)
No | メソッド / プロパティ | 説明 | 例 |
---|---|---|---|
1 | setGeometry(x, y, w, h) | ウィジェットの位置とサイズを設定 | widget.setGeometry(10, 10, 200, 100) |
2 | resize(w, h) | ウィジェットのサイズを変更 | widget.resize(300, 200) |
3 | move(x, y) | ウィジェットを指定位置へ移動 | widget.move(100, 50) |
4 | setFixedSize(w, h) | サイズを固定 | widget.setFixedSize(200, 150) |
5 | setMinimumSize(w, h) / setMaximumSize(w, h) | サイズの最小値・最大値を指定 | widget.setMinimumSize(100, 80) |
6 | update() | ウィジェットの再描画を要求 | widget.update() |
7 | repaint() | 即座に再描画を実行 | widget.repaint() |
8 | paintEvent(event) | ウィジェットの描画処理を定義 | def paintEvent(self, e): … |
9 | setStyleSheet(css) | CSS風の装飾を設定 | widget.setStyleSheet(“background-color: lightgreen;”) |
10 | setEnabled(bool) | ウィジェットの有効/無効を切り替え | widget.setEnabled(False) |
11 | setVisible(bool) / show() / hide() | 表示/非表示を切り替え | widget.hide() |
12 | setToolTip(text) | ツールチップを設定 | widget.setToolTip(“これは説明です”) |
13 | setCursor(cursor) | カーソル形状を変更 | widget.setCursor(Qt.PointingHandCursor) |
14 | mousePressEvent(event) | マウスクリックイベント処理 | def mousePressEvent(self, e): … |
15 | keyPressEvent(event) | キー入力イベント処理 | def keyPressEvent(self, e): … |
16 | closeEvent(event) | ウィンドウ閉じるときの処理 | def closeEvent(self, e): … |
各プロパティ・メソッド 詳細解説
【1】位置とサイズの設定
- 概要: ウィジェットの表示位置とサイズを一度に設定します。配置の座標系は親ウィジェットの左上が基準になります。
- メソッド:
setGeometry(x, y, width, height)
- 使い方:
# QWidgetをクラス継承
def __init__(self):
self.setGeometry(100, 50, 600, 200)

【2】サイズの変更
- 概要: ウィジェットのサイズだけを変更します。位置は変わりません。
- メソッド:
resize(width, height)
- 使い方:
# QWidgetをクラス継承
def __init__(self):
self.resize(400, 300)

【3】位置の移動
- 概要: ウィジェットを指定した座標に移動します。サイズは変わりません。
- メソッド:
move(x, y)
- 使い方:
# QWidgetをクラス継承
def __init__(self):
self.move(300, 50)
【4】サイズの固定
- 概要: ウィジェットのサイズを固定し、リサイズできないようにします。
- メソッド:
setFixedSize(width, height)
- 使い方:
# QWidgetをクラス継承
def __init__(self):
self.setFixedSize(250, 150)

【5】最小サイズ・最大サイズの設定
- 概要: ウィジェットのサイズ変更範囲を制限します。レイアウトを使用している場合にも有効です。
- メソッド:
setMinimumSize(width, height)
/setMaximumSize(width, height)
- 使い方:
# QWidgetをクラス継承
def __init__(self):
self.setMinimumSize(100, 80)
self.setMaximumSize(500, 400)
setMinimumSize | setMaximumSize |
---|---|
![]() | ![]() |
【6】再描画要求
概要:update()
は、「このウィジェットの見た目が変わったから、もう一度描画して!」とQtにお願いするメソッドです。
このメソッドを呼んだ瞬間に直接描画するわけではなく、Qtのイベントループを通して非同期的に paintEvent()
が呼び出されます。
そのため、画面の更新が必要な場面(色、形、文字、位置などが変わった時)で使用します。
- メソッド:
update()
- 使い方:
self.update() # paintEvent() が再度呼ばれる
- ウィジェットの状態が変化して描画内容も変える必要がある時に使います。
- 初期表示のときはQtが自動的に描画するので不要。
update()
は「お願い」だけで、すぐに描画しない → 安全に再描画ができる。- もし即座に描画したい場合は
repaint()
を使いますが、基本はupdate()
推奨。
【7】即時再描画
概要:repaint()
は、「今すぐ描画をやり直せ!」とQtに直接指示するメソッドです。update()
が「後で再描画してね」という予約型なのに対して、repaint()
は呼び出した瞬間に paintEvent()
を即座に実行します。
そのため、重い処理の途中などで使いすぎるとパフォーマンスが落ちる可能性があります。
- メソッド:
repaint()
- 使い方:
self.repaint() # すぐに再描画
- 即時描画が必要な場面(ユーザーに処理の進捗をリアルタイムに見せたいなど)で使う。
update()
よりも描画回数が増えやすく、処理負荷が高くなる場合がある。- 基本的には
update()
推奨。repaint()
は例外的な状況でのみ使用する。
【8】描画イベント
- 概要: カスタムウィジェットの見た目を描画するメソッドです。
QPainter
を使って自由に図形を描けます。 - メソッド:
paintEvent(event)
- 使い方:
def paintEvent(self, event):
painter = QPainter(self)
painter.setBrush(QColor("yellow"))
painter.drawEllipse(50, 50, 100, 100)

【9】スタイルシート設定
- 概要: CSS風の書式で見た目を変更します。色、枠線、背景などを簡単にカスタマイズ可能です。
- メソッド:
setStyleSheet(css)
- 使い方:
# QWidgetをクラス継承
def __init__(self):
self.setStyleSheet("border: 2px solid red; background-color: lightblue;")

【10】有効/無効の切り替え
- 概要: ウィジェットを操作可能にするか、無効化してグレーアウトするかを設定します。
- メソッド:
setEnabled(bool)
- 使い方:
# QWidgetをクラス継承
def __init__(self):
self.setEnabled(False) # 無効化
【11】表示・非表示の切り替え
- 概要: ウィジェットの表示状態を切り替えます。
show()
で表示、hide()
で非表示になります。 - メソッド:
setVisible(bool)
/show()
/hide()
- 使い方:
window.hide() # 非表示
window.show() # 表示
【12】ツールチップ設定
- 概要: ウィジェットにカーソルを合わせたときに表示される説明を設定します。
- メソッド:
setToolTip(text)
- 使い方:
# QWidgetをクラス継承
def __init__(self):
self.setToolTip("これは説明文です")

【13】カーソル形状の変更
- 概要: ウィジェット上にマウスカーソルがあるときの形を変更します。
- メソッド:
setCursor(cursor)
- 使い方:
from PySide6.QtCore import Qt
# QWidgetをクラス継承
def __init__(self):
self.setCursor(Qt.PointingHandCursor)
※スクリーンショットでマウスカーソルをキャプチャーできませんでした
【14】マウスイベント処理
- 概要: ウィジェットがクリックやドラッグされたときの動作を定義します。
- メソッド:
mousePressEvent(event)
- 使い方:
def mousePressEvent(self, event):
print(f"クリック位置: {event.position()}")
# クリック位置: PySide6.QtCore.QPointF(169.600000, 123.200000)
【15】キー入力イベント処理
- 概要: ウィジェットがフォーカスを持っている状態でキーが押されたときに処理を行います。
- メソッド:
keyPressEvent(event)
- 使い方:
def keyPressEvent(self, event):
print(f"押されたキー: {event.key()}")
# 押されたキー: 65
# 押されたキー: 70
【16】ウィンドウを閉じるイベント
- 概要: ウィンドウが閉じられる前に実行される処理を定義します。確認ダイアログを出すときに便利です。
- メソッド:
closeEvent(event)
- 使い方:
from PySide6.QtWidgets import QMessageBox
def closeEvent(self, event):
reply = QMessageBox.question(self, "確認", "本当に終了しますか?")
if reply == QMessageBox.Yes:
event.accept()
else:
event.ignore()

よくある質問(FAQ)
- paintEvent() はいつ呼ばれるのですか?
-
ウィンドウ表示時や、
update()
やresize()
を呼んだときに自動的に呼ばれます。 - QPainter の使い方で注意点は?
-
QPainter
はpaintEvent()
の中でのみ有効に使用してください。 - 独自のシグナルを持つカスタムウィジェットは作れますか?
-
可能です。
Signal()
をクラス変数に定義し、必要なタイミングでemit()
します。 - 複数のレイアウトを組み合わせたカスタムウィジェットは作れますか?
-
はい。
QVBoxLayout
やQHBoxLayout
を使って複合UIを作成できます。 - ウィジェットがちらつく場合の対策は?
-
setAttribute(Qt.WA_OpaquePaintEvent)
を設定すると描画の最適化が可能です。
まとめ
今回は、QWidgetを継承したカスタムウィジェットの作り方を解説しました。paintEvent()
を使えば自由な図形描画やデザインが可能で、シンプルなUIから高度なカスタムコンポーネントまで作成できます。
次回(第20回)は、「QGraphicsViewとQGraphicsSceneによるカスタム描画とシーン管理」について解説する予定です。

コメント