FFTによる声紋分析に操作ボタンを付ける
FFTによる声紋分析に操作ボタンを付けてみたのがこれ!

これは声紋表示を停止した状態です。表示再開ボタンを押せば再度動的に表示します。停止中はpngファイル出力ボタンにより画像を出力することができます。
PyQtGraphはグラフ表示だけてなくTkinterのようなウィジェットを扱うことができます。つまりPyQtGraphだけで画像アプリができてしまいます。
ソースです。

	import sys

import numpy as np
from PyQt5 import QtWidgets
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
#音声関係のライブラリ
import pyaudio
import pyqtgraph.exporters

class DrawFFT:
    def __init__(self):

        self.FFT_LEN = 1024
        self.RATE= 44100 #サンプリング周波数
        # 表示の停止
        self.stop = False
        # スペクトル表示バッファ
        self.tick_max_x = 200
        self.spct = np.full((self.tick_max_x, int(self.FFT_LEN / 2)), -150 )

        self.window = pg.GraphicsLayoutWidget(size=(500, 450), show=True)
        # 画像オブジェクト作成 & 画像をセット
        self.image = pg.ImageItem(border="y")
        self.image.setImage(self.spct)

        # カラーマップ取得・セット
        cmap = pg.colormap.getFromMatplotlib("jet")
        bar = pg.ColorBarItem( cmap=cmap, values=(-150, 0))
        bar.setImageItem(self.image) 

        # 画像を格納するボックス作成 & 画像オブジェクトをセット
        self.view_box = pg.ViewBox()
        # self.view_box.setAspectLocked(lock=True)
        self.view_box.addItem(self.image)
        

        # プロットオブジェクト作成、view_boxをセット
        self.plot = pg.PlotItem(viewBox=self.view_box)
        # ウィンドウにplotを追加
        self.window.addItem(self.plot)

        prox = QtGui.QGraphicsProxyWidget()
        layout = pg.LayoutWidget()
        self.btnStop = QtGui.QPushButton("停止")
        self.btnStop.clicked.connect(self.clicked)

        self.btnPng = QtGui.QPushButton("pngファイル出力")
        self.btnPng.clicked.connect(self.outPng)
        self.btnPng.setEnabled(False)

        layout.addWidget(self.btnStop, row=0, col=0)
        layout.addWidget(self.btnPng, row=0, col=1)
        prox.setWidget(layout)

        self.window.nextRow()
        self.window.addItem(prox)
        # ウィンドウ表示
        self.window.show()

        # PCM録音設定
        #音声データの格納場所(プロットデータ)
        self.fft_data=np.zeros(self.FFT_LEN)
        self.fft_cnt = 0
        self.received = False
        self.win_hamming = np.hamming(self.FFT_LEN)
       
        # self.CHUNK=1024  #1回の受信で読み取るデータ量
        self.audio=pyaudio.PyAudio()
        self.stream=self.audio.open(format=pyaudio.paInt16,
                                    channels=1,
                                    rate=self.RATE,
                                    input=True,
                                    frames_per_buffer=self.FFT_LEN,
                                    stream_callback=self.callback)

        self.stream.start_stream()


        #アップデート時間設定
        self.timer=QtCore.QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(20)

    def clicked(self):
        if self.stop == False:
            self.stop = True
            self.btnStop.setText("表示再開")
            self.btnPng.setEnabled(True)
        else:
            self.stop = False
            self.btnStop.setText("停止")
            self.btnPng.setEnabled(False)
    
    def outPng(self):
        # pngファイルにグラフを出力
        #  exportersの直前に pg.QtGui.QApplication.processEvents() を呼ぶ!
        pg.QtGui.QApplication.processEvents()
        exporter = pg.exporters.ImageExporter(self.window.scene())
        exporter.export("sono_graph.png")    

    def callback(self, in_data, frame_count, time_info, status):
        self.fft_data=np.frombuffer(in_data, dtype="int16")/32768.0
        self.received = True
        return (in_data,pyaudio.paContinue)


    def update(self):
        if self.stop == True:
            return

        if self.received == True:
            fft = np.fft.fft(self.fft_data * self.win_hamming)
            f = fft[0 : int(self.FFT_LEN / 2)]
            power_sp = 20 * np.log10(np.abs(f))
            # print(power_sp.max(), power_sp.min())
            if self.fft_cnt >= self.tick_max_x:
                temp =self.spct[1:]
                self.spct = np.insert(temp, -1, power_sp, axis=0)
            else:
                self.spct[self.fft_cnt] = power_sp
                self.fft_cnt += 1
            self.image.setImage(self.spct)
            self.received = False
     
    # デストラクタ
    def __del__(self):
       print('terminated.')
       self.stream.stop_stream()
       self.stream.close()
       self.audio.terminate()

if __name__=="__main__":
    plotwin=DrawFFT()
    if (sys.flags.interactive!=1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()
	
PyQtGraphのウィジェットは情報が少なく時間がかかります。
先ずはボタンの生成と配置
ボタンを1つだけならもっと簡単にできたのですが、同じ行に2個のボタンを作りました。

        self.btnStop = QtGui.QPushButton("停止")
        self.btnStop.clicked.connect(self.clicked)

        self.btnPng = QtGui.QPushButton("pngファイル出力")
        self.btnPng.clicked.connect(self.outPng)
        self.btnPng.setEnabled(False)	
ボタンはQtGui.QPushButtonオブジェクトで実装します。
clicked.connect()でイベントハンドラーをセットします。
ボタンの使用不可をsetEnabled()でセットします。

        layout.addWidget(self.btnStop, row=0, col=0)
        layout.addWidget(self.btnPng, row=0, col=1)
次に2個のボタンを layout.addWidget()でセットします。

        prox.setWidget(layout)

        self.window.nextRow()
        self.window.addItem(prox)
layoutをproxにセットします。
 最後にFFT表示の下の行に進めて、self.windowのアイテム追加をします。

ボタンの操作

ボタンの名称変更:
setText("表示再開")

ボタンの使用不可:
setEnabled(False)