2013年7月1日月曜日

PyQtの勉強をしてみる。 その5 matplotlibのsubplotでグラフを増やす

以前のプログラムを少し改良してadd_subplotでグラフを追加できるようにしてみる。
実装にあたってのポイントは2つあったのでメモしとこ。

まず、そのままadd_subplot(211)とかやると前の描画が残ってそこに上書きされるんで、それを消去する必要があった。delaxesでaxesを初期化する。

データ毎にリセットするのが速度的にどうかと思ったけど、今回の用途ではリアルタイム性を追求していないので、これでも良いかと。
for ax in self.fig.axes: #delete axes first
            self.fig.delaxes(ax)

もう一つはSignal/Slotに関して。Slotの引数を使いたいとき。
具体的には、QPushuButtonのclickedのSignalが出されたときにSlotの関数に引数を渡したい。
探した中で一番スマートだったのがここ。(以前もお世話になった)
スロットの部分にlambdaを使って渡している。
self.data_button.clicked.connect(lambda: self.barplot.add_data(np.random.rand(4)))

以下全文

import sys

import numpy as np
from PyQt4.QtGui import *
from PyQt4.QtCore import *

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure


class BarPlot():
    def __init__(self, parent=None):
        
        # Create the mpl Figure and FigCanvas objects.
        # 5x4 inches, 100 dots-per-inch
        self.dpi = 100
        self.fig = Figure((5,4), dpi=self.dpi)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(parent)        
        self.axes = self.fig.add_subplot(111)        
        self.data = []


    def on_draw(self):
        """
        redraw the figure
        """
        self.axes.clear()
        self.axes.grid()
        
        if len(self.data):
            for i, d in enumerate(self.data):
                self.axes = self.fig.add_subplot(len(self.data), 1, i+1)
                x = range(len(d))
                self.axes.bar(left=x, height=d, width=0.3, align='center',
                              alpha=0.44, picker=5)

        self.canvas.draw()
    
    def add_data(self, data):
        for ax in self.fig.axes: #delete axes first
            self.fig.delaxes(ax)
            
        self.data.append(data)
        self.on_draw()
        
        
class DataButton(QPushButton):    
    def __init__(self, *args):
        QPushButton.__init__(self, *args)
        self.setText("Add Data")

    
class AppForm(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.creat_main_window()
        self.barplot.on_draw()

    def creat_main_window(self):
        self.main_frame = QWidget()
        self.barplot = BarPlot(self.main_frame)
        self.data_button = DataButton(self.main_frame)
        self.data_button.clicked.connect(lambda: self.barplot.add_data(np.random.rand(4)))
        
        #set layout
        vbox = QVBoxLayout()
        vbox.addWidget(self.barplot.canvas)
        vbox.addWidget(self.data_button)

        self.main_frame.setLayout(vbox)

        #set widget
        self.setCentralWidget(self.main_frame)
        
        
def main(args):
    app = QApplication(args)
    form = AppForm()
    form.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main(sys.argv)


0 件のコメント:

コメントを投稿