目次
pyqtgraphを使おうと思った経緯
諸般の事情で、手っ取り早くクラウド側で蓄えてあるデータを可視化したいという要求ができまして。私の周りはIT関連に疎い方ばかりではあるのですが、それでも私以外の方もちょろっと触って良い感じに微調整したいという要求もちょっとあるので(本当に触りたいんだな?ニヤリ)、ちょっとやってぱっとできる、というのを満たすためにpythonを使って作りたい、と思ったわけです。pythonには一応tkinterとmatplotlibは標準で入っていますが「かっこよく作りたいな」という謎の要求仕様があるため?であればqt使おうと思ったわけです。たださすがにpyqtで頑張る気にはならなかったので(いっぺんやりかけましたけど辛いわあれ)グラフ描画に特化したライブラリであるpyqtgraphを使ってみようと思った次第です。
最近のpyqtgraph
pyqtgraph自身が持っているAPIでそこそこのものは作れそう
少し前のpyqtgraphは本当にグラフ描画中心で、周辺のボタンとかテーブルとかはpyqtと混ぜて使用する例が多くあったかと記憶していますが、最新のバージョンではそんなこともなくて、結構な数のQtWidgetが使えるようにAPIが生えていますね。私は今回はボタンとテキストボックス、そしてテーブルくらいがあれば十分だったので、それだったらあえてpyqtを混ぜなくてもpyqtgraphの中である程度閉じて書けるようになってきています。ところが、インターネット上でもサンプル例が多くないので、どのように書くのが一番楽かというのが分かりづらいのが難点ですね。テーブルとグラフ描画のみを作りたいですって場合はこんな感じで行けそうです。
def Setup_Window():
win = pg.LayoutWidget() # 親ウインドウはこれ
graph = pg.GraphicsLayoutWidget() # グラフを格納するレイアウトマネージャはこれ
table = pg.TableWidget() # テーブルウィジェットを作る
table.setData([["会社A", "2000", "4000"],["会社B", "1200", "60"]])
table.resizeRowsToContents()
win.addWidget(table, row = 0, col = 0) # テーブルを上1行に
win.addWidget(graph, row = 1, col = 0) # グラフを下1行に配置
x = np.arange(1000)
y = np.random.normal(size=(3, 1000))
for i in range(3):
graph.addPlot(title = "データ" + str(i), x = x, y = y[i], pen=(i,3)) # 適当なデータでグラフ3つこしらえてみた
return win
if __name__ == '__main__':
app = pg.mkQApp()
win = Setup_Window()
win.show()
app.exec_()

ドキュメントは貧相とは言わないが・・・初学者向きにはできていません
ドキュメントは結構ちゃんと書かれている方だとは思いますが、python + Qtアプリケーションとしてどのように完結させればちゃんとしたアプリケーションになるのか、という点はあまり書かれておりません。インタラクティブシェル上で1行ずつ打ち込んでいって、ほらグラフプロットできたでしょ?というようなチュートリアルになっているイメージですね。そのため、グラフ以外にもウィジェット生成や操作に関するAPIが生えているけれど、果たしてどう使うんだろう?というのが初学者にはぱっとは分からない、というのが現状ですね。とりあえず気にすることとしては、
- QApplicationクラスのオブジェクトを作成するにはpyqtgraph.mkQApp()メソッドを呼ぶ。これをしていないと、残りのQWidgetを作ろうとしたときエラーになります。
pyqt5と無理矢理混ぜると訳が分からなくなるので、素直にmkQAppを呼んだ方がよろしいかと思います。 - ウィンドウ側のイベントハンドラに移るためにはQApplicationクラスのオブジェクトにてexec_()メソッドを読んで終わる。こうするとウィンドウが閉じたときにアプリケーションが正常に終わることができます。
ここはQapplicationオブジェクトを取れさえすればpyqt5と変わりありません。 - QWidgetクラスのウィジェットを入れるウィンドウやレイアウトマネージャを作成したいなら、pyqtgraph.LayoutWidget()メソッドを呼ぶ必要がある。これに対して、グラフや画像など、グラフィック関連のものを入れるウィンドウやレイアウトマネージャを作成したい場合はpyqtgraph.GraphicLayoutWidget()メソッドを呼ぶ。
厳密なことを言えばQtウィジェットのクラス階層を知っておく必要がありますが、画面部品としてのウィジェットであるQWidgetとグラフ等のグラフィック関連のQGraphicsViewとは別物であって、それらを整形表示するためのレイアウトも分かれています。さらにpyqtgraphのAPIでは、LayoutWidgetメソッド・GraphicsLayoutWidgetメソッドが単体で呼ばれた場合はそのまま親ウィンドウになれます(し、別のウィンドウの中にレイアウトマネージャとして押し込めることもできます)。・・・というところが分かりにくい!のですが、そういう作りなんだから仕方がないですね。
こんな感じで
どこまで表現できるか、試していきたいと思います。足らなかったらQt + C++での拡張を考えないとダメかな?とも思いますが、ぱっと見そこまで大変そうでもないし・・・。