Как запустить анимационный класс matplotlib и PyQt5 Video в python одновременно
Я получил этот код с этого сайта, и я хочу объединить анимацию Matplotlib и просмотра видео. Он использует Pyqt5 QvideoWidget для воспроизведения видео и использует анимацию matplotlib для построения динамического графика. Но есть проблема, что анимация и видео не работали вместе. Но они работают отдельно. Я пытаюсь поместить Analog Class в Canvas, но это не удалось. Я думаю, что использование Canvas - это ответ, но я думаю, что мне нужна помощь, чтобы сделать это...
Спасибо
import numpy as np
from collections import deque
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.widgets import Button, Slider
from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia, QtMultimediaWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class AnalogPlot:
def __init__(self, data, display_len):
self.buff = deque(np.zeros(display_len))
self.display_len = display_len
self.data = data
# set up the plot
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111, xlim=(0, t_max), ylim=(-1, 1))
self.ax.set_xticks((0,t_max))
self.lines = self.ax.plot([], [])
# setup the animation
self.cur_frame = 0
self.anim = animation.FuncAnimation(self.fig, self._update,
interval=1.0)
# setup the animation control
self.anim_running = True
def _add_to_buff(self, buf, val):
if len(buf) < self.display_len:
buf.appendLeft(val)
else:
buf.popleft()
buf.append(val)
def _update(self, frame):
frame = self.cur_frame
self._add_to_buff(self.buff, self.data[frame:frame+1])
self.lines[0].set_data(range(self.display_len), self.buff)
self.ax.set_xticklabels((str(frame), str(frame+self.display_len)))
self.time_slider.eventson = False
self.time_slider.set_val(frame)
self.time_slider.eventson = True
self.cur_frame += 1
return self.lines
def _pause(self, event):
if self.anim_running:
self.anim.event_source.stop()
self.anim_running = False
else:
self.anim.event_source.start()
self.anim_running = True
def _reset(self, event):
self._set_val(0)
def _set_val(self, frame=0):
frame = int(frame)
self.cur_frame = frame
new_start = frame - self.display_len
if new_start >= 0:
self.buff = deque(self.data[new_start:frame])
else:
self.buff = deque(np.concatenate((np.zeros(np.abs(new_start)), self.data[:frame])))
self.anim.event_source.stop()
self.anim = animation.FuncAnimation(self.fig, self._update,
interval=1.0)
self.anim_running = True
def animate(self):
pause_ax = self.fig.add_axes((0.7, 0.025, 0.1, 0.04))
pause_button = Button(pause_ax, 'pause', hovercolor='0.975')
pause_button.on_clicked(self._pause)
reset_ax = self.fig.add_axes((0.8, 0.025, 0.1, 0.04))
reset_button = Button(reset_ax, 'reset', hovercolor='0.975')
reset_button.on_clicked(self._reset)
slider_ax = self.fig.add_axes((0.1, 0.025, 0.5, 0.04))
self.time_slider = Slider(slider_ax, label='Time',
valmin=0, valmax=self.data.shape[0],
valinit=0.0)
self.time_slider.on_changed(self._set_val)
plt.show()
class VideoWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(VideoWindow, self).__init__(parent)
self.setWindowTitle("PyQt Video Player Widget Example - pythonprogramminglanguage.com")
self.mediaPlayer = QtMultimedia.QMediaPlayer(self, QtMultimedia.QMediaPlayer.VideoSurface)
videoWidget = QtMultimediaWidgets.QVideoWidget()
self.playButton = QtWidgets.QPushButton()
self.playButton.setEnabled(False)
self.playButton.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_MediaPlay))
self.playButton.clicked.connect(self.play)
self.positionSlider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.positionSlider.setRange(0, 0)
self.positionSlider.sliderMoved.connect(self.setPosition)
self.errorLabel =QtWidgets.QLabel()
self.errorLabel.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
# Create new action
openAction = QtWidgets.QAction(QtGui.QIcon('open.png'), '&Open', self)
openAction.setShortcut('Ctrl+O')
openAction.setStatusTip('Open movie')
openAction.triggered.connect(self.openFile)
# Create exit action
exitAction = QtWidgets.QAction(QtGui.QIcon('exit.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.exitCall)
# Create menu bar and add action
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
#fileMenu.addAction(newAction)
fileMenu.addAction(openAction)
fileMenu.addAction(exitAction)
# Create a widget for window contents
wid = QtWidgets.QWidget()
self.setCentralWidget(wid)
# Create layouts to place inside widget
controlLayout = QtWidgets.QHBoxLayout()
controlLayout.setContentsMargins(0, 0, 0, 0)
controlLayout.addWidget(self.playButton)
controlLayout.addWidget(self.positionSlider)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(videoWidget)
layout.addLayout(controlLayout)
layout.addWidget(self.errorLabel)
# Set widget to contain window contents
wid.setLayout(layout)
self.mediaPlayer.setVideoOutput(videoWidget)
self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
self.mediaPlayer.positionChanged.connect(self.positionChanged)
self.mediaPlayer.durationChanged.connect(self.durationChanged)
self.mediaPlayer.error.connect(self.handleError)
def openFile(self):
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open Movie", QtCore.QDir.homePath())
if fileName:
media = QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(fileName))
self.mediaPlayer.setMedia(media)
self.playButton.setEnabled(True)
def exitCall(self):
QtWidgets.QApplication.quit()
def play(self):
if self.mediaPlayer.state() == QtMultimedia.QMediaPlayer.PlayingState:
self.mediaPlayer.pause()
else:
self.mediaPlayer.play()
def mediaStateChanged(self, state):
if self.mediaPlayer.state() == QtMultimedia.QMediaPlayer.PlayingState:
self.playButton.setIcon(
self.style().standardIcon(QtWidgets.QStyle.SP_MediaPause))
else:
self.playButton.setIcon(
self.style().standardIcon(QtWidgets.QStyle.SP_MediaPlay))
def positionChanged(self, position):
self.positionSlider.setValue(position)
def durationChanged(self, duration):
self.positionSlider.setRange(0, duration)
def setPosition(self, position):
self.mediaPlayer.setPosition(position)
def handleError(self):
self.playButton.setEnabled(False)
self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
player = VideoWindow()
player.resize(640, 480)
player.show()
t_max = 100
lin_sig = np.linspace(0, 1, 1000)
analog_plot = AnalogPlot(lin_sig, t_max)
analog_plot.animate()
sys.exit(app.exec_())