簡體   English   中英

PyQt5中的Matplotlib-Graph在運行時不會更新

[英]Matplotlib-Graph in PyQt5 not updating while running

我是新來的,希望我的問題就在這里。 我正在嘗試對GUI進行編程,在該GUI中我可以記錄麥克風中的某些聲音並實時繪制,以查看聲音的左右聲道。

我在GUI和Matplotlib-FigureCanvas中使用PyQt 5進行繪圖。 流媒體工作正常,但是該圖僅在記錄停止后顯示,並且在記錄過程中不會像應有的那樣更新。 在調試模式下,每次可以更新圖時,都可以看到它們,但是當我運行代碼時,GUI會凍結,直到完成記錄為止。 那是因為繪圖太慢嗎? 我用動畫或線程嘗試了不同的方法,但到目前為止沒有任何效果。

我想最終獲得一個實時更新的情節,如何實現呢? 還有更長的錄音時間嗎?

希望有人能幫助我,在此先感謝!

這是我的代碼部分,在其中進行記錄和繪圖:

import sys
from PyQt5 import QtGui, QtWidgets, QtCore
import numpy as np
import time
import pyaudio
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.gridspec as gridspec
import matplotlib.animation as animation


class Window(QtWidgets.QMainWindow):

  def __init__(self):  # sort of template for rest of GUI, is always there, menubar/ mainmenu eg.
      super(Window, self).__init__()
      self.setGeometry(50, 50, 1500, 900)
      self.setWindowTitle("PyQt Tutorial!")

      self.centralwidget = QtWidgets.QWidget(self)
      self.centralwidget.setObjectName("centralwidget")

      self.channels = 2
      self.fs = 44100  # samplerate
      self.Chunks = 1024

      self.tapeLength = 2  # seconds
      self.tape = np.empty(self.fs * self.tapeLength) * np.nan  # tapes where recorded audio is stored
      self.taper = np.empty(self.fs * self.tapeLength) * np.nan
      self.tapel = np.empty(self.fs * self.tapeLength) * np.nan

      self.home()

  def home(self):
      btn = QtWidgets.QPushButton("Stream and Plot", self)  # Button to start streaming
      btn.clicked.connect(self.plot)
      btn.resize(btn.sizeHint())
      btn.move(100, 100)

      self.scrollArea = QtWidgets.QScrollArea(self)
      self.scrollArea.move(75, 400)
      self.scrollArea.resize(600, 300)
      self.scrollArea.setWidgetResizable(False)

      self.scrollArea2 = QtWidgets.QScrollArea(self)
      self.scrollArea2.move(775, 400)
      self.scrollArea2.resize(600, 300)
      self.scrollArea2.setWidgetResizable(False)
      self.scrollArea.horizontalScrollBar().valueChanged.connect(self.scrollArea2.horizontalScrollBar().setValue)
      self.scrollArea2.horizontalScrollBar().valueChanged.connect(self.scrollArea.horizontalScrollBar().setValue)

      self.figure = Figure((15, 2.8), dpi=100)  # figure instance (to plot on) F(width, height, ...)
      self.canvas = FigureCanvas(self.figure)
      self.scrollArea.setWidget(self.canvas)
      self.toolbar = NavigationToolbar(self.canvas, self.scrollArea)

      self.canvas2 = FigureCanvas(self.figure)
      self.scrollArea2.setWidget(self.canvas2)
      self.toolbar2 = NavigationToolbar(self.canvas2, self.scrollArea2)

      self.gs = gridspec.GridSpec(1, 1)
      self.ax = self.figure.add_subplot(self.gs[0])
      self.ax2 = self.figure.add_subplot(self.gs[0])
      self.figure.subplots_adjust(left=0.05)

      self.ax.clear()

  def start_streamsignal(self, start=True):
      # open and start the stream
      if start is True:
          print("start Signals")

          self.p = pyaudio.PyAudio()
          self.stream = self.p.open(format=pyaudio.paFloat32, channels=self.channels, rate=self.fs, input_device_index=1,
                             output_device_index=5, input=True, frames_per_buffer=self.Chunks)
          print("recording...")

  def start_streamread(self):
      """return values for Chunks of stream"""
      data = self.stream.read(self.Chunks)
      npframes2 = np.array(data).flatten()
      npframes2 = np.fromstring(npframes2, dtype=np.float32)

      norm_audio2 = (npframes2 / np.max(np.abs(npframes2)))  # normalize
      left2 = norm_audio2[::2]
      right2 = norm_audio2[1::2]
      print(norm_audio2)
      return left2, right2

  def tape_add(self):
      """add chunks to tape"""
      self.tape[:-self.Chunks] = self.tape[self.Chunks:]
      self.taper = self.tape
      self.tapel = self.tape
      self.taper[-self.Chunks:], self.tapel[-self.Chunks:] = self.start_streamread()

  def plot(self, use_blit=True):
      # Plot the Tape and update chunks
      print('Plotting')
      self.start_streamsignal(start=True)
      start = True

      for duration in range(0, 15, 1):
          plotsec = 1
          time.sleep(2)
          self.timeArray = np.arange(self.taper.size)
          self.timeArray = (self.timeArray / self.fs) * 1000  # scale to milliseconds
          self.tape_add()

          # self.canvas.draw()
          while start is True and plotsec < 3:

              # self.ani = animation.FuncAnimation(self.figure, self.animate, interval=25, blit=True)
              self.ax2.plot(self.taper, '-b')
              self.canvas.draw()

              self.ax2.clear()
              self.ax2.plot(self.tapel, 'g-')
              self.canvas2.draw()

              plotsec += 1

  def animate(self):
      self.line.set_xdata(self.taper)
      return self.line,


def main():
    app = QtWidgets.QApplication(sys.argv)
    GUI = Window()
    GUI.show()
    sys.exit(app.exec_())

main()

在了解完整的代碼以及那里的所有東西實際上應該做什么時,我確實遇到了嚴重的問題。 因此,我現在只能告訴您的是擺脫循環並使用FuncAnimation來顯示動畫。

  def plot(self, use_blit=True):
      # Plot the Tape and update chunks
      print('Plotting')
      self.start_streamsignal(start=True)
      start = True
      self.line, = self.ax2.plot([],[], '-b')
      self.ax.set_xlim(0, len(self.tape))
      self.ax2.set_xlim(0, len(self.tape))
      self.ax.set_ylim(-3, 3)
      self.ax2.set_ylim(-3, 3)

      self.ani = animation.FuncAnimation(self.figure, self.animate, frames=100, 
                                         interval=25, blit=use_blit)


  def animate(self,i):
      self.timeArray = np.arange(self.taper.size)
      self.timeArray = (self.timeArray / self.fs) * 1000  # scale to milliseconds
      self.tape_add()
      self.line.set_data(range(len(self.taper)),self.taper)
      return self.line,

感謝所有幫助,如果有人感興趣,這是現​​在可以使用的代碼:

import sys
from PyQt5 import QtGui, QtWidgets, QtCore
import numpy as np
import time
import pyaudio
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.gridspec as gridspec
import matplotlib.animation as animation


class Window(QtWidgets.QMainWindow):

  def __init__(self):  # sort of template for rest of GUI, is always there, menubar/ mainmenu eg.
      super(Window, self).__init__()
      self.setGeometry(50, 50, 1500, 900)
      self.setWindowTitle("PyQt Tutorial!")

      self.centralwidget = QtWidgets.QWidget(self)
      self.centralwidget.setObjectName("centralwidget")

      self.channels = 2
      self.fs = 44100  # samplerate
      self.Chunks = 1024

      self.tapeLength = 2  # seconds
      self.tape = np.empty(self.fs * self.tapeLength) * np.nan  # tapes where recorded audio is stored

      self.home()

  def home(self):
      btn = QtWidgets.QPushButton("Stream and Plot", self)  # Button to start streaming
      btn.clicked.connect(self.plot)
      btn.resize(btn.sizeHint())
      btn.move(100, 100)

      self.scrollArea = QtWidgets.QScrollArea(self)
      self.scrollArea.move(75, 400)
      self.scrollArea.resize(600, 300)
      self.scrollArea.setWidgetResizable(False)

      self.scrollArea2 = QtWidgets.QScrollArea(self)
      self.scrollArea2.move(775, 400)
      self.scrollArea2.resize(600, 300)
      self.scrollArea2.setWidgetResizable(False)
      self.scrollArea.horizontalScrollBar().valueChanged.connect(self.scrollArea2.horizontalScrollBar().setValue)
      self.scrollArea2.horizontalScrollBar().valueChanged.connect(self.scrollArea.horizontalScrollBar().setValue)

      self.figure = Figure((15, 2.8), dpi=100)  # figure instance (to plot on) F(width, height, ...)
      self.canvas = FigureCanvas(self.figure)
      self.scrollArea.setWidget(self.canvas)
      self.toolbar = NavigationToolbar(self.canvas, self.scrollArea)

      self.canvas2 = FigureCanvas(self.figure)
      self.scrollArea2.setWidget(self.canvas2)
      self.toolbar2 = NavigationToolbar(self.canvas2, self.scrollArea2)

      self.gs = gridspec.GridSpec(1, 1)
      self.ax = self.figure.add_subplot(self.gs[0])
      self.ax2 = self.figure.add_subplot(self.gs[0])
      self.figure.subplots_adjust(left=0.05)

      self.ax.clear()

  def start_streamsignal(self, start=True):
  # open and start the stream
      if start is True:
          print("start Signals")

          self.p = pyaudio.PyAudio()
          self.stream = self.p.open(format=pyaudio.paFloat32, channels=self.channels, rate=self.fs, input_device_index=1,
                         output_device_index=5, input=True, frames_per_buffer=self.Chunks)
          print("recording...")

  def start_streamread(self):
  """return values for Chunks of stream"""
      data = self.stream.read(self.Chunks)
      npframes2 = np.array(data).flatten()
      npframes2 = np.fromstring(npframes2, dtype=np.float32)

      norm_audio2 = (npframes2 / np.max(np.abs(npframes2)))  # normalize
      left2 = norm_audio2[::2]
      right2 = norm_audio2[1::2]
      print(norm_audio2)
      return left2, right2

  def tape_add(self):
  """add chunks to tape"""
      self.tape[:-self.Chunks] = self.tape[self.Chunks:]
      self.taper = self.tape
      self.tapel = self.tape
      self.taper[-self.Chunks:], self.tapel[-self.Chunks:] = self.start_streamread()

  def plot(self, use_blit=True):
  # Plot the Tape and update chunks
      print('Plotting')
      self.start_streamsignal(start=True)
      start = True

      for duration in range(0, 15, 1):
          QtWidgets.QApplication.processEvents()
          plotsec = 1
          time.sleep(2)
          self.timeArray = np.arange(self.taper.size)
          self.timeArray = (self.timeArray / self.fs) * 1000  # scale to milliseconds
          self.tape_add()

          while start is True and plotsec < 3:

              self.ax.plot(self.taper, '-b')
              self.canvas.draw()

              self.ax2.clear()
              self.ax2.plot(self.tapel, 'g-')
              self.canvas2.draw()

              plotsec += 1


def main():
    app = QtWidgets.QApplication(sys.argv)
    GUI = Window()
    GUI.show()
    sys.exit(app.exec_())

main()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM