簡體   English   中英

在 function 中調用 FuncAnimation()

[英]Calling FuncAnimation() when it is inside a function

我試圖在調用特定的 function 時執行 FuncAnimation()。 但是,我在 plot 中沒有得到任何結果。

當 FuncAnimation 不在 function 內(或在 __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_())

解決方案是為它更新繪畫,有兩個選項:使用self.canvas.draw()或在FuncAnimation中設置blit=True

除了上面你還有一個錯誤是假設一個信號和一個槽之間的連接返回了被調用的 function 的結果,這是錯誤的,連接返回一個變量,表明連接是否成功。 另一個錯誤是您在 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_())

暫無
暫無

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

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