Как запустить анимационный класс 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_())

0 ответов

Другие вопросы по тегам