\ 迷ったらまずTechAcademyの無料カウンセリング! /
PySide Model/View【第1弾】表・一覧表示を本格運用!QTableView + QStandardItemModel

表や一覧表示を「とりあえず動かす」なら QTableWidget が手軽ですが、大量データ・外部ソース(CSV/DB/API)・再利用性 を考えると Model/View 方式が圧倒的に便利です。
本記事では QTableView(表示) と QStandardItemModel(データ) を組み合わせ、拡張性の高い表UIを作る基礎を丁寧に解説します。
「セルをどう埋めるか」ではなく、「データをどう設計して表示に渡すか」という発想に切り替えるのがポイントです。
QTableView + QStandardItemModelとは?
QTableView は「データを表(テーブル)として表示するための部品」です。
一方の QStandardItemModel は「表に入れるデータを管理する入れ物」です。
この2つを組み合わせると、ボタンを配置するのと同じ感覚で 表形式のデータ表示 が作れます。
たとえば、エクセルのように「行と列があって、その中に文字や数値を入れる」というイメージです。
初心者の方は、まず「QTableWidget」で表を作ってみて、
そのあと「QTableView + QStandardItemModel」に進むと、もっと自由度の高いアプリを作れるようになります。

基本コード
from PySide6.QtWidgets import QApplication, QMainWindow, QTableView
from PySide6.QtGui import QStandardItemModel, QStandardItem
from PySide6.QtCore import Qt
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("QTableView + QStandardItemModel 入門")
# 1) モデル作成(行3・列2)
model = QStandardItemModel(3, 2, self)
model.setHorizontalHeaderLabels(["名前", "年齢"])
# 2) データ投入(QStandardItem を使う)
model.setItem(0, 0, QStandardItem("Alice"))
model.setItem(0, 1, QStandardItem("23"))
model.setItem(1, 0, QStandardItem("Bob"))
model.setItem(1, 1, QStandardItem("31"))
model.setItem(2, 0, QStandardItem("Charlie"))
model.setItem(2, 1, QStandardItem("28"))
# 3) View にモデルをセット
view = QTableView(self)
view.setModel(model)
# 4) 使い勝手向上(任意)
view.setSortingEnabled(True) # ヘッダクリックでソート
view.setSelectionBehavior(QTableView.SelectRows) # 行単位選択
view.resizeColumnsToContents() # 列幅自動調整
self.setCentralWidget(view)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.resize(500, 300)
w.show()
sys.exit(app.exec())

- View(見た目) と Model(データ) を分離して扱うため、データ差し替えや複数ビュー共有が簡単。
QStandardItemModel
は汎用モデル。自作データ構造と厳密に結びつけたい場合はQAbstractTableModel
に発展できます。
主なプロパティとメソッド一覧(全解説)
No | メソッド / プロパティ | 説明 | 例 |
---|---|---|---|
1 | view.setModel(model) / view.model() | View に Model を設定 / 取得 | view.setModel(model) |
2 | model.setRowCount(n) / model.setColumnCount(n) | 行・列数の設定 | model.setRowCount(10) |
3 | model.rowCount() / model.columnCount() | 行・列数の取得 | print(model.rowCount()) |
4 | model.setHorizontalHeaderLabels(list) | 列ヘッダー名の一括設定 | model.setHorizontalHeaderLabels(["A","B"]) |
5 | model.setItem(r,c,QStandardItem) / model.item(r,c) | Item の設定 / 取得 | model.setItem(0,0,QStandardItem("x")) |
6 | model.index(r,c) / model.data(index, role) / model.setData(index, value, role) | QModelIndex を介したデータ取得/設定 | model.setData(model.index(0,0),"x") |
7 | model.insertRow(r) / model.removeRow(r) / insertColumn/ removeColumn | 行列の挿入・削除 | model.insertRow(1) |
8 | model.clear() | モデル内容をクリア(ヘッダ含む) | model.clear() |
9 | view.setSortingEnabled(True) / model.sort(col, order) | ソートの有効化 / 実行 | model.sort(1, Qt.AscendingOrder) |
10 | view.setEditTriggers(flags) | 編集可否(ダブルクリック等) | view.setEditTriggers(QTableView.NoEditTriggers) |
11 | view.setSelectionBehavior(mode) / view.setSelectionMode(mode) | 行/セル単位選択・単数/複数選択 | view.setSelectionBehavior(QTableView.SelectRows) |
12 | view.resizeColumnsToContents() / resizeRowsToContents() | 内容に応じた自動サイズ調整 | view.resizeColumnsToContents() |
13 | view.horizontalHeader() / view.verticalHeader() | ヘッダーの詳細設定 | view.horizontalHeader().setStretchLastSection(True) |
14 | item.setEditable(bool) / item.setCheckable(bool) など | アイテムの属性(編集可・チェック等) | item.setEditable(False) |
15 | model.itemFromIndex(index) / model.indexFromItem(item) | Index ⇔ Item 変換 | item = model.itemFromIndex(idx) |
16 | model.findItems(text, flags, column) | 文言でアイテム検索 | model.findItems("Bob") |
各プロパティ・メソッド 詳細解説
【1】Model を View に関連付ける
概要:表示(View)にデータ(Model)を渡します。
メソッド:view.setModel(model)
/ view.model()
使い方:
# 1) モデル作成(行3・列2)
model = QStandardItemModel(3, 2, self)
# 3) View にモデルをセット
view = QTableView(self)
view.setModel(model)
m = view.model()
print(m)
# <PySide6.QtGui.QStandardItemModel(0x183ed8921c0) at 0x00000183EDF54C40>
【2】行数・列数の設定
概要:表のサイズを変更します。
メソッド:setRowCount(int)
/ setColumnCount(int)
使い方:
model.setRowCount(8)
model.setColumnCount(5)

【3】行数・列数の取得
概要:現在のサイズを調べます。
メソッド:rowCount()
/ columnCount()
使い方:
rows = model.rowCount()
cols = model.columnCount()
print(f'列数:{rows}')
print(f'行数:{cols}')
# 列数:8
# 行数:5
【4】列ヘッダーの設定
概要:見出しを一括設定します。
メソッド:setHorizontalHeaderLabels(list)
使い方:
model.setHorizontalHeaderLabels(["名前", "年齢", "部署"])

【5】Item の設定・取得
概要:QStandardItem
を直接入れたり取り出します。
メソッド:setItem(row, col, QStandardItem)
/ item(row, col)
使い方:
item = QStandardItem("MIsa")
item.setEditable(False)
model.setItem(0, 0, item)
text = model.item(0, 0).text()
print(text)
# Misa

【6】QModelIndex を介したデータ入出力
概要:index(row,col)
でインデックスを作り、data/setData
で値や表示属性(role)を操作します。
メソッド:index()
/ data(index, role)
/ setData(index, value, role)
使い方:
idx = model.index(0, 1)
model.setData(idx, 42, role=Qt.DisplayRole)
val = model.data(idx, Qt.DisplayRole)
print(f'idx = {idx}')
print(f'val = {val}')
# idx = <PySide6.QtCore.QModelIndex(0,1,0x173c3e01df0,QStandardItemModel(0x173c4959020)) at 0x00000173C5044840>
# val = 42

【7】行・列の挿入/削除
概要:途中行・列の追加や削除。
メソッド:insertRow()
/ removeRow()
/ insertColumn()
/ removeColumn()
使い方:
model.insertRow(1)
model.removeColumn(0)

【8】モデルのクリア
概要:中身を全消去(ヘッダーも消える)。
メソッド:clear()
使い方:
model.clear()

【9】ソートの有効化/実行
概要:ヘッダークリックでソート、またはコードで明示的にソート。
メソッド:view.setSortingEnabled(True)
/ model.sort(column, order)
使い方:
view.setSortingEnabled(True) # UIでソート可能
model.sort(2, Qt.AscendingOrder) # コードで実行

【10】編集可否
概要:セルを編集可能にする条件(クリック操作など)を制御。
メソッド:view.setEditTriggers(flags)
使い方:
from PySide6.QtWidgets import QAbstractItemView as AIV
view.setEditTriggers(AIV.NoEditTriggers) # 編集不可
# 例: AIV.DoubleClicked, AIV.SelectedClicked, AIV.AllEditTriggers など
例 | 説明 |
---|---|
view.setEditTriggers(QAbstractItemView.DoubleClicked) | 編集できるタイミングを設定 |
view.setEditTriggers(QAbstractItemView.NoEditTriggers) | 編集不可 |
view.setEditTriggers(QAbstractItemView.CurrentChanged) | カレントセルが変わった時に編集可 |
view.setEditTriggers(QAbstractItemView.DoubleClicked) | ダブルクリックで編集可 |
view.setEditTriggers(QAbstractItemView.SelectedClicked) | 選択中のセルをクリックで編集可 |
view.setEditTriggers(QAbstractItemView.EditKeyPressed) | EnterキーやF2キーで編集可 |
view.setEditTriggers(QAbstractItemView.AnyKeyPressed) | 文字入力で即編集開始 |
view.setEditTriggers(QAbstractItemView.AllEditTriggers) | すべてのトリガーで編集可 |
view.setSelectionMode(QAbstractItemView.SingleSelection) | 選択方法を設定 |
view.setSelectionMode(QAbstractItemView.NoSelection) | 選択不可 |
view.setSelectionMode(QAbstractItemView.SingleSelection) | 1セルのみ選択可 |
view.setSelectionMode(QAbstractItemView.MultiSelection) | 複数セル選択可(Ctrlクリック) |
view.setSelectionMode(QAbstractItemView.ExtendedSelection) | 複数セル選択可(ShiftやCtrl併用) |
view.setSelectionBehavior(QAbstractItemView.SelectRows) | 選択対象(セル・行・列)を設定 |
view.setSelectionBehavior(QAbstractItemView.SelectItems) | セル単位で選択 |
view.setSelectionBehavior(QAbstractItemView.SelectRows) | 行単位で選択 |
view.setSelectionBehavior(QAbstractItemView.SelectColumns) | 列単位で選択 |
【11】選択挙動
概要:行/セル単位の選択や複数選択可否を制御。
メソッド:view.setSelectionBehavior(mode)
/ view.setSelectionMode(mode)
使い方:
from PySide6.QtWidgets import QAbstractItemView as AIV
view.setSelectionBehavior(AIV.SelectRows) # 行単位
view.setSelectionMode(AIV.SingleSelection) # 単一選択
【12】列・行サイズの自動調整
概要:内容に合わせて列・行サイズを合わせる。
メソッド:resizeColumnsToContents()
/ resizeRowsToContents()
使い方:
view.resizeColumnsToContents()

【13】ヘッダーの詳細設定
概要:ヘッダーの表示制御や伸縮設定。
メソッド:horizontalHeader()
/ verticalHeader()
使い方:
hh = view.horizontalHeader()
hh.setStretchLastSection(True) # 最終列を余白に合わせる
view.verticalHeader().setVisible(False) # 行番号非表示

例 | 説明 |
---|---|
view.horizontalHeader().setVisible(False) | ヘッダーを非表示にする |
view.horizontalHeader().setStretchLastSection(True) | 最後の列を自動で幅調整する |
view.horizontalHeader().setDefaultSectionSize(120) | デフォルトの列幅を設定 |
view.horizontalHeader().resizeSection(0, 200) | 特定の列幅を変更 |
view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) | 列幅をウィンドウサイズに合わせて自動調整 |
view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) | 内容に応じて列幅を自動調整 |
view.verticalHeader().setVisible(False) | 行番号を非表示にする |
view.verticalHeader().setDefaultSectionSize(40) | 行の高さを設定 |
view.verticalHeader().setSectionResizeMode(QHeaderView.Fixed) | 行の高さを固定 |
view.verticalHeader().hide() | 行ヘッダーを完全に隠す(ショートカット) |
【14】アイテム属性(編集/チェック/フォント等)
概要:QStandardItem
に対して属性を設定。
メソッド:item.setEditable(bool)
/ item.setCheckable(bool)
など
使い方:
it = QStandardItem("完了")
it.setCheckable(True)
it.setEditable(False)
model.setItem(0, 2, it)
【15】Index ⇔ Item 変換
概要:QModelIndex
と QStandardItem
を相互に変換。
メソッド:itemFromIndex(index)
/ indexFromItem(item)
使い方:
idx = model.index(0, 0) # QModelIndex
item = model.itemFromIndex(idx) # QStandardItem
idx2 = model.indexFromItem(item) # QModelIndex
【16】アイテム検索
概要:モデル内から文字列を検索して、該当するアイテムをリストで返す
メソッド:findItems(text, flags=Qt.MatchContains, column=-1)
引数 | 説明 | 例 |
---|---|---|
text: str | 検索する文字列 | "Python" |
flags: Qt.MatchFlag | マッチ条件を指定 | Qt.MatchExactly (完全一致), Qt.MatchStartsWith (前方一致), Qt.MatchContains (部分一致), Qt.MatchEndsWith (後方一致), Qt.MatchRegExp (正規表現検索)など |
column: int | 検索対象の列を指定 | 0 (1列目), 2 (3列目) |
使い方:
hits = model.findItems("Bob", Qt.MatchContains, 0) # 0列目から検索
for it in hits:
print(it.text())
# Bob
よくある質問(FAQ)
- QTableWidget との違いは?
-
QTableWidget は手軽ですが、データと見た目が密結合。QTableView は Model と分離でき、再利用・複数ビュー・外部データ連携で有利です。
- セル編集を禁止したい
-
view.setEditTriggers(QAbstractItemView.NoEditTriggers)
または個別アイテムでitem.setEditable(False)
。 - 大量データで遅い
-
QStandardItemModel
は汎用性重視。数十万行などはQAbstractTableModel
(必要時に data を供給)+QTableView
を検討。 - ソート/フィルタは?
-
ソートは
view.setSortingEnabled(True)
。フィルタはQSortFilterProxyModel
を View と Model の間に挟みます。 - 文字色やフォントを変えたい
-
model.setData(index, QBrush(Qt.red), Qt.ForegroundRole)
やQt.FontRole
を使用。 - チェック付きの列を作りたい
-
QStandardItem
にsetCheckable(True)
。値はitem.checkState()
/item.setCheckState()
。 - 最終列をウィンドウ幅にフィットさせたい
-
view.horizontalHeader().setStretchLastSection(True)
。 - CSV/DB を表示したい
-
CSV は読み込んで
QStandardItemModel
に流し込み、DB はQSqlTableModel + QTableView
が便利
まとめ
QTableView + QStandardItemModel は、表・一覧表示を 拡張性高く 構築できる王道パターンです。setModel
で表示とデータを分け、setItem
/ setData
/ insertRow
等で柔軟に編集できます。
ソート・選択・編集可否・サイズ調整などの UI も QTableView
側で一括制御できて便利。
次のステップは QSortFilterProxyModel(ソート/フィルタ強化)や、QAbstractTableModel(独自データ源の高速表示)です。
コメント