Вызов FuncAnimation (), когда он находится внутри функции - PullRequest
1 голос
/ 04 мая 2020

Я пытаюсь выполнить FuncAnimation () при вызове указанной c функции. Тем не менее, я не получаю никакого результата на своем графике.

Когда FuncAnimation не находится внутри функции (или внутри __init __ ()), тогда он работает отлично.

Я перепробовал все уже опубликованные решения связанные с этой проблемой, но они не работают в моем коде.

Мой упрощенный код:

import sys
import os
from datetime import datetime
import matplotlib
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QSizePolicy, QWidget
import numpy as np
import random
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.animation import FuncAnimation

class MyMplCanvas(FigureCanvas):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)

        self.ax = fig.add_subplot(1,1,1)

        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self,
                                   QtWidgets.QSizePolicy.Expanding,
                                   QtWidgets.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.main_widget = QtWidgets.QWidget(self)
        self.canvas =  MyMplCanvas( self.main_widget,width=6, height=6, dpi=100) 

        self.xdata = []
        self.ydata = []

        vbox = QtWidgets.QVBoxLayout(self.main_widget)

        self.start_button = QtWidgets.QPushButton(text="START")
        self.outer_ani = self.start_button.clicked.connect(self.start_func_animation)

        vbox.addWidget(self.canvas)
        vbox.addWidget(self.start_button)
        self.setLayout(vbox)
        self.main_widget.setFocus()
        self.setCentralWidget(self.main_widget)

    def start_func_animation(self):
        self.line, = self.canvas.ax.plot_date(self.xdata, self.ydata, linestyle='-', linewidth=0.6, markersize=2.5)
        self.ani = FuncAnimation(self.canvas.figure, self.update_line, interval=1000)

        return self.ani

    def update_line(self, i):
        self.xdata.append(datetime.now())
        self.ydata.append(1+np.random.randint(-3,3))

        self.line.set_data(self.xdata, self.ydata)
        self.canvas.figure.gca().relim()
        self.canvas.figure.gca().autoscale_view()
        self.canvas.ax.tick_params(axis='x', rotation=50)

        return self.line,


if __name__ == "__main__":
    App = QApplication(sys.argv)
    aw = ApplicationWindow()
    aw.show()
    App.exit()
    sys.exit(App.exec_())

1 Ответ

1 голос
/ 05 мая 2020

Решение состоит в том, чтобы обновить картину, для этого есть 2 варианта: использовать self.canvas.draw() или установить blit=True в FuncAnimation.

В дополнение к вышесказанному у вас также есть еще одна ошибка, предполагающая что соединение между сигналом и слотом возвращает результат вызванной функции, и это ложно, соединение возвращает переменную, которая указывает, было ли соединение успешным или нет. Другая ошибка заключается в том, что вы излишне устанавливаете макет в QMainWindow, и это невозможно, потому что QMainWindow уже имеет макет по умолчанию. Наконец, использование quit () не имеет смысла.

from datetime import datetime
import random
import os
import sys

from PyQt5 import QtCore, QtWidgets

import numpy as np

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.animation import FuncAnimation


class MyMplCanvas(FigureCanvas):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)

        self.ax = fig.add_subplot(1, 1, 1)

        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(
            self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding
        )
        FigureCanvas.updateGeometry(self)


class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.main_widget = QtWidgets.QWidget(self)
        self.canvas = MyMplCanvas(self.main_widget, width=6, height=6, dpi=100)

        self.xdata = []
        self.ydata = []

        vbox = QtWidgets.QVBoxLayout(self.main_widget)

        self.start_button = QtWidgets.QPushButton(text="START")
        # self.outer_ani = self.start_button.clicked.connect(self.start_func_animation)
        self.start_button.clicked.connect(self.start_func_animation)

        vbox.addWidget(self.canvas)
        vbox.addWidget(self.start_button)
        # self.setLayout(vbox)
        self.main_widget.setFocus()
        self.setCentralWidget(self.main_widget)

    def start_func_animation(self):
        (self.line,) = self.canvas.ax.plot_date(
            self.xdata, self.ydata, linestyle="-", linewidth=0.6, markersize=2.5
        )
        self.canvas.draw()
        self.ani = FuncAnimation(self.canvas.figure, self.update_line, interval=1000)
        # or
        # self.ani = FuncAnimation(self.canvas.figure, self.update_line, interval=1000, blit=True)
        # return self.ani

    def update_line(self, i):
        self.xdata.append(datetime.now())
        self.ydata.append(1 + np.random.randint(-3, 3))

        self.line.set_data(self.xdata, self.ydata)
        self.canvas.figure.gca().relim()
        self.canvas.figure.gca().autoscale_view()
        self.canvas.ax.tick_params(axis="x", rotation=50)

        return (self.line,)


if __name__ == "__main__":
    App = QtWidgets.QApplication(sys.argv)
    aw = ApplicationWindow()
    aw.show()
    # App.exit()
    sys.exit(App.exec_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...