#python #animation #matplotlib #pyqt4
#python #Анимация #matplotlib #pyqt4
Вопрос:
Я нашел эту классную анимацию для Matlibplot и хочу добавить ее в свой виджет plot в программе Pyqt. Это метод, который успешно отображает регулярные графики в моей программе
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()
Ответ №1:
Вы можете использовать найденный код, просто измените свой метод на:
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.hold(False)
, и вполне вероятно, что анимация будет работать медленнее при использовании сюжетных линий (попробуйте увеличить разрешение [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()