\ 迷ったらまずTechAcademyの無料カウンセリング! /
PySide Model/View【第7弾】GUIグラフ連携!Matplotlib × QTableViewで動的チャートを作る

前回までは テーブルやツリー、リストの表示や操作 を中心に学んできました。
今回は一歩進んで、QTableView に入力したデータを Matplotlib のグラフにリアルタイム反映させる方法を解説します。
GUIアプリでは「データを表形式で入力 → グラフで可視化」という流れはよくあるパターンです。
例えば、
- 売上データを表に入力し、グラフで動的に表示
- センサー値をテーブルで管理し、その変化を折れ線グラフに反映
- 実験データを入力してすぐに可視化
といったケースに応用できます。
ここでは QTableView + QStandardItemModel をベースにし、Matplotlib と連携する仕組みを紹介します。
Matplotlib連携と完成コード
PySideのModel/View機構とMatplotlibを組み合わせると、次のような動的アプリが作れます:
- QTableViewに数値を入力
- モデル(QStandardItemModel)が更新される
- MatplotlibのFigureに再描画を要求
- チャートが最新データを反映して表示される
つまり「モデルがデータ管理」「ビューが表表示」「Matplotlibが可視化」という役割分担になります。
Matplotlibに関する使い方は下記記事を参考にしてください

完成アプリ:折れ線グラフと棒グラフの切り替え
折れ線グラフ | 棒グラフ |
---|---|
![]() | ![]() |
完成コード:折れ線グラフと棒グラフの切り替え
import sys
from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QTableView
)
from PySide6.QtGui import QStandardItemModel, QStandardItem, QFont
from PySide6.QtCore import Qt
# Matplotlib(Qt連携用)
from matplotlib.backends.backend_qt5agg import (
FigureCanvasQTAgg as FigureCanvas,
NavigationToolbar2QT as NavigationToolbar
)
from matplotlib.figure import Figure
class TableGraphApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QTableView × Matplotlib Demo")
self.resize(800, 600)
# レイアウト
layout = QVBoxLayout(self)
# モデルとビュー
self.model = QStandardItemModel(5, 2) # 5行2列
self.model.setHorizontalHeaderLabels(["X", "Y"])
self.view = QTableView()
self.view.setModel(self.model)
# Matplotlibグラフ
self.figure = Figure()
self.canvas = FigureCanvas(self.figure)
self.ax = self.figure.add_subplot(111)
# ツールバー
self.toolbar = NavigationToolbar(self.canvas, self)
# レイアウトに追加
layout.addWidget(self.view)
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
# データ変更時にグラフ更新
self.model.dataChanged.connect(self.update_plot)
# 初期データをセット
self.set_initial_data()
self.update_plot()
def set_initial_data(self):
"""初期データをモデルにセット"""
data = [(1, 10), (2, 15), (3, 8), (4, 12), (5, 18)]
for row, (x, y) in enumerate(data):
self.model.setItem(row, 0, QStandardItem(str(x)))
self.model.setItem(row, 1, QStandardItem(str(y)))
def update_plot(self):
"""テーブルのデータを読み取り、グラフを更新"""
x, y = [], []
for row in range(self.model.rowCount()):
item_x = self.model.item(row, 0)
item_y = self.model.item(row, 1)
if item_x and item_y: # Noneチェック
try:
x_val = float(item_x.text())
y_val = float(item_y.text())
x.append(x_val)
y.append(y_val)
except ValueError:
continue # 数値に変換できない場合はスキップ
# グラフ更新
self.ax.clear()
if x and y:
self.ax.plot(x, y, marker="o", linestyle="-", color="blue", label="Data")
self.ax.set_xlabel("X")
self.ax.set_ylabel("Y")
self.ax.set_title("Dynamic Plot from QTableView", fontname='Meiryo')
self.ax.legend()
self.canvas.draw_idle()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TableGraphApp()
window.show()
sys.exit(app.exec())
主なプロパティとメソッド一覧(全体解説)
No | プロパティ / メソッド | 説明 |
---|---|---|
1 | QApplication(...) / app.exec() | Qt アプリケーションの作成とイベントループ開始。app.exec() で GUI のメインループを回します。 |
2 | QWidget.show() | ウィンドウ(またはウィジェット)を画面に表示します。 |
3 | setWindowTitle(title) | ウィジェット(ウィンドウ)のタイトルバーに表示する文字列を設定します。 |
4 | resize(w, h) | ウィジェットの初期サイズを指定します。 |
5 | QVBoxLayout() / addWidget(widget) | 垂直レイアウトを作り、子ウィジェットを追加します。 |
6 | QTableView.setModel(model) | テーブルビューにデータモデルをセットします。 |
7 | QStandardItemModel(rows, cols) / setHorizontalHeaderLabels(labels) | 標準アイテムモデルの生成(行数・列数指定)とヘッダラベルの設定。 |
8 | QStandardItemModel.setItem(row, col, item) | 指定セルに QStandardItem をセットします。 |
9 | QStandardItemModel.rowCount() | モデルの行数を取得します(ループなどで利用)。 |
10 | QStandardItemModel.item(row, col) | 指定セルの QStandardItem を取得します。 |
11 | dataChanged (シグナル) | モデル内のデータが編集されたときに発火するシグナル。 |
12 | QStandardItem(text) / QStandardItem.text() | セルに入れる標準アイテムの生成と、そのテキスト取得。 |
13 | QComboBox.addItems(list) | コンボボックスに複数の選択肢を追加します。 |
14 | QComboBox.currentIndexChanged / currentText() | 選択変更のシグナルと、現在選択中のテキスト取得。 |
15 | Figure() / Figure.add_subplot() | Matplotlib の Figure (図)の生成と描画領域(Axes)の生成。 |
16 | FigureCanvasQTAgg(Figure) | Matplotlib 図を Qt ウィジェットに埋め込むラッパー(キャンバス)。 |
17 | NavigationToolbar2QT(canvas, parent) | Matplotlib の表示ツールバー(ズームや保存など)を追加するウィジェット。 |
18 | Axes.clear() / Axes.plot() / Axes.bar() / Axes.set_xlabel() / set_ylabel() / set_title() / legend() | 描画(折れ線 / 棒グラフ)の実行とラベル/タイトルの設定、凡例表示。 |
19 | FigureCanvas.draw_idle() | 描画を要求(非同期的で効率的)。更新を画面に反映します。 |
20 | signal.connect(slot) (一般) | Qt のシグナルとスロット(関数)を接続する基本パターン。 |
各プロパティ・メソッド 詳細解説
【1】 Qtアプリの開始
概要:Qt アプリケーションのエントリポイントです。QApplication
を生成してから app.exec()
を呼ぶことでイベントループが開始され、GUI が動作します。
メソッド:QApplication(...) / app.exec()
使い方:
import sys
from PySide6.QtWidgets import QApplication
app = QApplication(sys.argv)
# ウィンドウを作って show() する...
sys.exit(app.exec()) # イベントループ開始、戻り値で終了コードを返す
【2】 ウィンドウ画面の表示
概要:ウィジェットを画面に表示します。show()
することでウィンドウがマップされます。
メソッド:QWidget.show()
使い方:
window = TableGraphApp()
window.show()
【3】 ウィンドウのタイトル
概要:ウィンドウ(トップレベルウィジェット)のタイトルを設定します。日本語でも問題ありません
メソッド:setWindowTitle(title)
使い方:
self.setWindowTitle("QTableView × Matplotlib Demo")
【4】 ウィンドウの初期サイズ
概要:ウィンドウの初期サイズ(幅,高さ)をピクセル単位で指定します。
メソッド:resize(w, h)
使い方:
self.resize(800, 600)
【5】 垂直レイアウト
概要:垂直方向にウィジェットを配置するレイアウト。addWidget()
で子要素を追加します。
メソッド:QVBoxLayout()
/ addWidget(widget)
使い方:
# レイアウト
layout = QVBoxLayout(self)
# レイアウトに追加
layout.addWidget(self.view) # QTableView
layout.addWidget(self.toolbar) # Matplotlib ツールバー
layout.addWidget(self.graph_selector_label)
layout.addWidget(self.graph_selector)
layout.addWidget(self.canvas) # FigureCanvas
【6】 テーブルビューにデータセット
概要:QTableView
にデータソース(モデル)をセットします。ビューはモデルのデータを描画します。
メソッド:QTableView.setModel(model)
使い方:
self.view = QTableView()
self.view.setModel(self.model)
【7】標準アイテムモデルの生成
概要:QStandardItemModel
は簡単に使える汎用モデルです。コンストラクタで行列サイズを与え、ヘッダラベルを設定できます。
メソッド:QStandardItemModel(rows, cols)
/ setHorizontalHeaderLabels(labels)
使い方:
self.model = QStandardItemModel(5, 2) # 5行2列
self.model.setHorizontalHeaderLabels(["X", "Y"])
【8】 QStandardItem のセット
概要:指定位置に QStandardItem
を置きます。セルを編集可能にしたい場合は QStandardItem
を使います。
メソッド:QStandardItemModel.setItem(row, col, item)
使い方:
from PySide6.QtGui import QStandardItem
data = [(1, 10), (2, 15), (3, 8), (4, 12), (5, 18)]
for row, (x, y) in enumerate(data):
self.model.setItem(row, 0, QStandardItem(str(x)))
self.model.setItem(row, 1, QStandardItem(str(y)))
【9】 モデルの現在の行数
概要:モデルの現在の行数を返します。ループで全行を処理するときによく使います。
メソッド:QStandardItemModel.rowCount()
使い方:
for r in range(self.model.rowCount()):
# item を取得して処理
【10】 指定セルの取得
概要:指定セルの QStandardItem
を取得します(存在しない場合は None
)。取得後 .text()
で中身の文字列を得られます。
メソッド:QStandardItemModel.item(row, col)
使い方:
item_x = self.model.item(row, 0)
if item_x:
text = item_x.text()
# 1
# 1
# 1
# 2
# 1
# 2
# 1
# 2
.......
【11】 データ編集時のシグナル
概要:モデル内のデータが編集されたときに Qt が発するシグナルです。ビューが編集されるとこのシグナルが飛びます。
メソッド:dataChanged
(シグナル)
使い方:
self.model.dataChanged.connect(self.update_plot)
【12】 セルに格納するアイテムの作成
概要:セルに格納するアイテムを作ります。テキストの取得は .text()
。
メソッド:QStandardItem(text)
/ QStandardItem.text()
使い方:
item = QStandardItem("123")
s = item.text()
# "123"
【13】コンボボックスへの追加
概要:複数の項目をまとめてコンボボックスへ追加します。
メソッド:QComboBox.addItems(list)
使い方:
self.graph_selector.addItems(["折れ線グラフ", "棒グラフ"])
【14】 選択変更時のシグナル
概要:選択が変わったときに発火するシグナル(currentIndexChanged
)と、現在選択されているテキストを取得する currentText()
。
メソッド:QComboBox.currentIndexChanged
/ currentText()
使い方:
self.graph_selector.currentIndexChanged.connect(self.update_plot)
typ = self.graph_selector.currentText()
# 折れ線グラフ
【15】 Matplotlib の図オブジェクト
概要:Matplotlib の図オブジェクト(Figure
)を作り、add_subplot()
で描画領域(Axes
)を得ます。
メソッド:Figure()
/ Figure.add_subplot()
(Matplotlib)
使い方:
from matplotlib.figure import Figure
self.figure = Figure()
self.ax = self.figure.add_subplot(111)

【16】 グラフをウィジェットに埋め込み
概要:Matplotlib の Figure を Qt のウィジェットとして表示するためのラッパー。これをレイアウトに入れることで Matplotlib グラフを埋め込みます。
メソッド:FigureCanvasQTAgg(Figure)
使い方:
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
self.canvas = FigureCanvas(self.figure)
layout.addWidget(self.canvas)
【17】 Matplotlib の標準ツールバー
概要:Matplotlib の標準ツールバー(ズーム、パン、保存など)を表示するウィジェット。canvas
と親ウィジェットを渡して生成します。
メソッド:NavigationToolbar2QT(canvas, parent)
使い方:
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
self.toolbar = NavigationToolbar(self.canvas, self)
layout.addWidget(self.toolbar)
【18】 描画のための主要メソッド
概要:描画のための主要メソッド群です。前の描画を消す clear()
、折れ線 plot()
、棒グラフ bar()
、ラベルやタイトル、凡例の設定。
メソッド:Axes.clear()
/ Axes.plot()
/ Axes.bar()
/ set_xlabel()
/ set_ylabel()
/ set_title()
/ legend()
使い方(抜粋):
self.ax.clear()
self.ax.plot(x, y, marker="o", linestyle="-")
self.ax.set_xlabel("X")
self.ax.set_ylabel("Y")
self.ax.set_title("タイトル")
self.ax.legend()

【19】 キャンバス上の描画更新
概要:キャンバス上の描画更新を要求します。draw()
と違い、イベントループのアイドル時に効率よく再描画されるため UI の応答性が良くなります。
メソッド:FigureCanvas.draw_idle()
使い方:
self.canvas.draw_idle()
【20】 Qt のシグナルとの接続
概要:Qt のシグナル(イベント)と任意の関数(スロット)を結びつける基本操作。上のdataChanged.connect(self.update_plot)
や currentIndexChanged.connect(...)
がこれに該当します。
メソッド:signal.connect(slot)
(一般)
使い方:
self.model.dataChanged.connect(self.update_plot)
self.graph_selector.currentIndexChanged.connect(self.update_plot)
よくある質問Q&A
- グラフ更新が遅いのですが?
-
canvas.draw_idle()
を使うと効率よく描画できます。 - テーブル以外からもデータを追加したい
-
model.setItem()
やinsertRow()
を使えばプログラム的に追加可能です。 - Matplotlibのグラフを別ウィンドウに表示できますか?
-
はい。
figure.show()
で独立したウィンドウ表示も可能です。 - グラフの凡例やタイトルは?
-
Matplotlib標準API (
ax.set_title
,ax.legend
) をそのまま使えます。 - Pandasのデータフレームと連携できますか?
-
可能です。DataFrameをモデルに変換して
QTableView
に渡せば、そのままグラフに反映できます。
まとめ
- QTableView + QStandardItemModel をデータ入力のUIに利用
- dataChangedシグナル → update_plot() でグラフを自動更新
- MatplotlibをQtに組み込むことで、GUI上で 入力と可視化のループ が作れる
- 実用例:データ分析ツール、センサー監視、売上ダッシュボード
Model/Viewの基礎を学んだら、こうした 動的なデータ可視化 に進むと応用力が一気に高まります。
コメント