我想根據 GUI 提供的值以互動方式更改 matplotlib.animation 引數。
例子:
- 我準備了一個示例代碼,如下所示,我試圖根據用戶通過使用 tkinter 創建的 spinBox 提供的值來更改影片的間隔引數。
問題:
- 為了能夠更新它的引數,我想將我的影片呼叫到旋轉框呼叫的回呼函式中。但如果我這樣做,我會收到以下錯誤訊息“用戶警告:影片被洗掉而沒有渲染任何東西。這很可能是無意的。為防止洗掉,請將影片分配給只要您需要影片就存在的變數。”
- 如果我將我的影片呼叫到主代碼中,那么我將無法以互動方式更改它的引數
問題:
- 如何以互動方式更改影片引數,即基于用戶可以在 tkinter 小部件中設定的值?
示例代碼:
import tkinter as tk
from random import randint
import matplotlib as plt
import matplotlib.animation as animation
import matplotlib.backends.backend_tkagg as tkagg
#Creating an instance of the Tk class
win = tk.Tk()
#Creating an instance of the figure class
fig = plt.figure.Figure()
#Create a Canvas containing fig into win
aCanvas =tkagg.FigureCanvasTkAgg(fig, master=win)
#Making the canvas a tkinter widget
aFigureWidget=aCanvas.get_tk_widget()
#Showing the figure into win as if it was a normal tkinter widget
aFigureWidget.grid(row=0, column=0)
#Defining the animation
ax = fig.add_subplot(xlim=(0, 1), ylim=(0, 1))
(line,) = ax.plot([],[], '-')
CumulativeX, CumulativeY = [], []
# Providing the input data for the plot for each animation step
def update(i):
CumulativeX.append(randint(0, 10) / 10)
CumulativeY.append(randint(0, 10) / 10)
return line.set_data(CumulativeX, CumulativeY)
spinBoxValue=1000
#When the button is pushed, get the value
def button():
spinBoxValue=aSpinbox.get()
#Running the animation
ani=animation.FuncAnimation(fig, update, interval=spinBoxValue, repeat=True)
#Creating an instance of the Spinbox class
aSpinbox = tk.Spinbox(master=win,from_=0, to=1000, command=button)
#Placing the button
aSpinbox .grid(row=2, column=0)
#run the GUI
win.mainloop()
uj5u.com熱心網友回復:
我們必須fig.canvas.draw()在函式內部創建影片時重新繪制影片button:
def button():
global spinBoxValue, CumulativeX, CumulativeY, ani
spinBoxValue = aSpinbox.get()
CumulativeX, CumulativeY = [], [] # This is optional
# To stop the background animation
ani.event_source.stop()
# Unlink/delete the reference to the previous animation
# del ani
ani=animation.FuncAnimation(fig, update, interval=int(spinBoxValue) * 1000, repeat=False)
fig.canvas.draw()
在提供的代碼中,它在使用 from 的值重新創建影片時繪制線條太快,因此我將輸入更改為整數,以便在函式內部aSpinbox.get()以較慢的速度繪制影片。interval=int(spinBoxvalue) * 1000button
關于洗掉影片
由于我們必須在按下按鈕時停止背景影片并運行新生成的影片,并且因為影片必須存盤在變數中,只要它運行,我們將不得不參考以前和最新的影片相同的變數名。
ani我們可以使用del aniafter洗掉全域變數中存盤的影片ani.event_source.stop(),這會丟失對按下按鈕之前存盤在記憶體中的影片的參考,但我們不能真正釋放參考 by的記憶體地址ani(我是只要我們在 Python 中使用默認的垃圾收集方法,猜測這就是真的)。
編輯
跳轉到新影片不會更新/洗掉此處在軸上創建的任何變數 - 我們必須明確處理它。要在按下按鈕后僅更新一次變數,首先在代碼的全域范圍內創建這些變數,然后在button函式內洗掉它們并在使用之前/之后重新創建/定義它們fig.canvas.draw:
# Defined in global scope
text = ax.text(0.7, 0.5, "text")
def button():
global spinBoxValue, CumulativeX, CumulativeY, ani, text
spinBoxValue = int(aSpinbox.get())
# To stop the background animation
ani.event_source.stop()
CumulativeX, CumulativeY = [], []
# Unlink/delete the reference to the previous animation
# del ani
text.remove()
text = ax.text(0.7 * spinBoxValue/10 , 0.5, "text")
ani=animation.FuncAnimation(fig, update, interval=spinBoxValue*1000, repeat=False)
fig.canvas.draw()
相同的邏輯可以應用于使用update函式在每次按下按鈕后或每幀后重繪文本,同時使用button最頂部提供的函式:
text = ax.text(0.7, 0.5, "text")
# Providing the input data for the plot for each animation step
def update(i):
global text
text.remove()
# Update text after button press
# "text" is drawn at (0.7 * 1000/10, 0.5) when button = 0
text = ax.text(0.7 * spinBoxValue/10 , 0.5, "text")
# Comment previous line and uncomment next line to redraw text at every frame
# text = ax.text(0.7 * i/10 , 0.5, "text")
CumulativeX.append(randint(0, 10) / 10)
CumulativeY.append(randint(0, 10) / 10)
print(CumulativeX)
return line.set_data(CumulativeX, CumulativeY)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/521021.html
