2021-07-26

Qt for Python によるチャート (8)

Python で GUI アプリを作成するときに Qt の Python 用バインディングである PySide (Qt for Python) を使用することが多くなりました。散布図などのチャート作成には、もっぱら matplotlib を使っていますが、他の選択肢も検討しようと、QtCharts というチャート作成用ライブラリの使い方をまとめました。

当初、PySide 用の QtCharts のサンプルが見つからず、C++ 用のサンプル [1] を PySide 用に書き直していましたが、よく探してみると PySide 用サンプルもありました [2]。ここでは、勉強がてら C++ 用のサンプルを書き直したものを紹介していきます。

本記事では、下記の OS 環境を使用しています。

Fedora 34 Workstation x86_64
- Python 3.9.6
- PySide6 6.1.2 (venv)
- IDE: PyCharm 2021.1.3 (Community Edition)

ScatterChart(散布図)

ScatterChart(散布図)は、横軸と縦軸それぞれに別の量をとり、データが当てはまるところに点をプロットするグラフです。2つの量に関係があるかどうかをみるのに便利です。

qtcharts_scatterchart.py
#!/usr/bin/env python
# coding: utf-8
# Reference
# https://doc.qt.io/qt-6/qtcharts-scatterchart-example.html
import math
import sys
from PySide6.QtCharts import (
QChart,
QChartView,
QLegend,
QScatterSeries,
)
from PySide6.QtCore import (
QPointF,
Qt,
)
from PySide6.QtGui import (
QColor,
QImage,
QPainter,
QPainterPath,
)
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
)
class ScatterChart(QChartView):
def __init__(self):
super().__init__()
chart = self.init_ui()
self.setChart(chart)
self.setRenderHint(QPainter.Antialiasing)
def init_ui(self):
series1 = QScatterSeries()
series1.setName('scatter1')
series1.setMarkerShape(QScatterSeries.MarkerShapeCircle)
series1.setMarkerSize(15.0)
series2 = QScatterSeries()
series2.setName('scatter2')
series2.setMarkerShape(QScatterSeries.MarkerShapeRectangle)
series2.setMarkerSize(20.0)
series3 = QScatterSeries()
series3.setName('scatter3')
series3.setMarkerShape(QScatterSeries.MarkerShapeRectangle)
series3.setMarkerSize(30.0)
series1.append(0, 6)
series1.append(2, 4)
series1.append(3, 8)
series1.append(7, 4)
series1.append(10, 5)
series2 << QPointF(1, 1) << QPointF(3, 3) << QPointF(7, 6) << QPointF(8, 3) << QPointF(10, 2)
series3 << QPointF(1, 5) << QPointF(4, 6) << QPointF(6, 3) << QPointF(9, 5)
starPath = QPainterPath()
starPath.moveTo(28, 15)
for i in range(1, 6):
starPath.lineTo(14 + 14 * math.cos(0.8 * i * math.pi),
15 + 14 * math.sin(0.8 * i * math.pi))
starPath.closeSubpath()
star = QImage(30, 30, QImage.Format_ARGB32)
star.fill(Qt.transparent)
painter = QPainter(star)
painter.setRenderHint(QPainter.Antialiasing)
painter.setPen(QColor(246, 166, 37))
painter.setBrush(painter.pen().color())
painter.drawPath(starPath)
painter.end()
series3.setBrush(star)
series3.setPen(QColor(Qt.transparent))
chart = QChart()
chart.addSeries(series1)
chart.addSeries(series2)
chart.addSeries(series3)
chart.setTitle('Simple scatterchart example')
chart.createDefaultAxes()
chart.setDropShadowEnabled(False)
chart.legend().setMarkerShape(QLegend.MarkerShapeFromSeries)
return chart
class Example(QMainWindow):
def __init__(self):
super().__init__()
scatter = ScatterChart()
self.setCentralWidget(scatter)
self.resize(500, 300)
self.setWindowTitle('ScatterChart')
def main():
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()

実行例を下記に示しました。

qtcharts_scatterchart.py の実行例

QScatterSeries クラスのインスタンスに、表示するシンボル (Marker) の種類、大きさを指定して、データ列を定義するのが基本です。

        series = QScatterSeries()
        series.setName('scatter')
        series.setMarkerShape(QScatterSeries.MarkerShapeCircle)
        series.setMarkerSize(15.0)

        series.append(0, 6)
        series.append(2, 4)
        ...
        ...

サンプルでは series3 で星型のイメージを定義していますが、QPainterPath や QPainter クラスの使用経験が自分に不足していますので、経験を積んで別の機会に説明します。🙇🙏

参考サイト

  1. Qt Charts Examples | Qt Charts 6.1.2
  2. Qt for Python Examples — Qt for Python

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ Linuxへ
にほんブログ村

0 件のコメント: