Python 我可以在pyqt4的Matplotlib小部件中使用动画吗?

Python 我可以在pyqt4的Matplotlib小部件中使用动画吗?,python,animation,matplotlib,pyqt4,Python,Animation,Matplotlib,Pyqt4,我在Matlibplot中找到了这个很酷的动画,并希望将其添加到Pyqt程序中的plot小部件中。这是在我的程序中成功显示规则图的方法 def plot(self): ax = self.ui.figure.add_subplot(111) ax.hold(False) ax.plot([1,2,3],[4,5,6]) self.ui.canvas.draw() 我想我可以将动画代码中的单个def添加到我的表单中,并像上面一样调用动画,但遗憾的是,没有。下面是动

我在Matlibplot中找到了这个很酷的动画,并希望将其添加到Pyqt程序中的plot小部件中。这是在我的程序中成功显示规则图的方法

def plot(self):
    ax = self.ui.figure.add_subplot(111)
    ax.hold(False)
    ax.plot([1,2,3],[4,5,6])
    self.ui.canvas.draw()
我想我可以将动画代码中的单个def添加到我的表单中,并像上面一样调用动画,但遗憾的是,没有。下面是动画代码:

import numpy as np
import matplotlib.pyplot as plt 
import matplotlib.animation as animation

N = 100
ON = 255
OFF = 0
vals = [ON, OFF]

# populate grid with random on/off - more off than on
grid = np.random.choice(vals, N*N, p=[0.2, 0.8]).reshape(N, N)

    def update(data):
        global grid
        # copy grid since we require 8 neighbors for calculation
        # and we go line by line 
        newGrid = grid.copy()
        for i in range(N):
            for j in range(N):
            # compute 8-neghbor sum 
            # using toroidal boundary conditions - x and y wrap around 
            # so that the simulaton takes place on a toroidal surface.
            total = (grid[i, (j-1)%N] + grid[i, (j+1)%N] + 
                    grid[(i-1)%N, j] + grid[(i+1)%N, j] + 
                    grid[(i-1)%N, (j-1)%N] + grid[(i-1)%N, (j+1)%N] + 
                    grid[(i+1)%N, (j-1)%N] + grid[(i+1)%N, (j+1)%N])/255
            # apply Conway's rules
            if grid[i, j]  == ON:
                if (total < 2) or (total > 3):
                    newGrid[i, j] = OFF
            else:
                if total == 3:
                    newGrid[i, j] = ON
        # update data
    mat.set_data(newGrid)
    grid = newGrid
    return [mat]

# set up animation
fig, ax = plt.subplots()
mat = ax.matshow(grid)
ani = animation.FuncAnimation(fig, update, interval=50,
                          save_count=50)
plt.show()

您可以使用找到的代码,只需将方法更改为:

def plot(self):
    ax = self.ui.figure.add_subplot(111)
    global mat
    mat = ax.matshow(grid)
    ani = animation.FuncAnimation(figure, update, interval=50, save_count=50)
    self.ui.canvas.draw()
请注意,您不必使用ax.holdFalse,当使用subplotstry增加分辨率[N]以查看差异时,动画的运行速度可能会更慢。在我自己的项目中,我的3D绘图速度有这样的问题-非常令人沮丧=D

我使用类而不是全局变量制作了一个小示例程序,也许它很方便:

import sys
import numpy as np
from PyQt4 import QtGui

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas

from functools import partial 

class Game_of_life(QtGui.QWidget):
    def __init__(self, N, ON, OFF):
        super(Game_of_life, self).__init__()
        self.N = N
        self.ON = ON
        self.OFF = OFF
        self.vals = [ON, OFF]
        self.grid = np.random.choice(self.vals, N*N, p=[0.2, 0.8]).reshape(N, N)        
        self.start()

    def start(self):
        self.setWindowTitle('Game of life')
        gridLayout = QtGui.QGridLayout()    
        self.setLayout(gridLayout)

        #Figure and subplot
        figure = plt.figure()
        canvas = FigureCanvas(figure)
        ax = figure.add_subplot(111)
        canvas.draw()

        self.mat = ax.matshow(self.grid)
        ani = animation.FuncAnimation(figure, self.update, interval=50, save_count=50)

        #button
        restart = QtGui.QPushButton("Restart game of life")
        restart.clicked.connect(partial(self.restart_animation, ax=ax, figure=figure))

        gridLayout.addWidget(canvas,0,0)
        gridLayout.addWidget(restart, 1,0)

        self.show()
    def update(self, data):
        newGrid = self.grid.copy()
        for i in range(self.N):
            for j in range(self.N):
                total = (self.grid[i, (j-1)%self.N] + self.grid[i, (j+1)%self.N] + 
                        self.grid[(i-1)%self.N, j] + self.grid[(i+1)%self.N, j] + 
                        self.grid[(i-1)%self.N, (j-1)%self.N] + self.grid[(i-1)%self.N, (j+1)%self.N] + 
                        self.grid[(i+1)%self.N, (j-1)%self.N] + self.grid[(i+1)%self.N, (j+1)%self.N])/255
                if self.grid[i, j]  == self.ON:
                    if (total < 2) or (total > 3):
                        newGrid[i, j] = self.OFF
                else:
                    if total == 3:
                        newGrid[i, j] = self.ON
        self.mat.set_data(newGrid)
        self.grid = newGrid

    #simply restarts game data
    def restart_animation(self, ax, figure):
        self.grid = np.random.choice(self.vals, self.N*self.N, p=[0.2, 0.8]).reshape(self.N, self.N)
        self.mat = ax.matshow(self.grid)


def main():
    app = QtGui.QApplication(sys.argv)
    widget = Game_of_life(100, 255, 0)
    #widget can be implement in other layout
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()