无法在tkinter窗口中嵌入多个动画matplotlib图表
当第一次点击“实时次要任务图表”按钮时,次要图表的数据会嵌入到界面中,并且是动态的。不过,这时会生成两个空的主要图形,一个是由primary
对象创建的图表,另一个是由secondary
对象创建的图表。之后再点击“实时主要任务图表”按钮时,图表会重新加载,但界面上不会绘制出新的图表,同时我在终端上收到了一个错误信息,内容是:
用户警告:动画在没有渲染任何内容的情况下被删除。这很可能不是你想要的。为了防止被删除,请将动画赋值给一个变量,比如anim
,确保这个变量在你使用plt.show()
或anim.save()
输出动画之前一直存在。
下面是用于创建界面的模块:
import customtkinter as ctk
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from data_processing.primary_graph_data import PrimaryGraphData
from data_processing.secondary_graph_data import SecondaryGraphData
class App(ctk.CTk):
def __init__(self) -> None:
super().__init__()
self.geometry(f"{1100}x{580}")
self.tabview = ctk.CTkTabview(self, width=1080, height=570)
self.tabview.pack()
self.tabview.add("Live Primary Mission Graphs")
self.tabview.add("Live Secondary Mission Graphs")
#LIVE GRAPHS SETUP
primary = PrimaryGraphData()
canvas_primary = FigureCanvasTkAgg(primary.primaryfig, self.tabview.tab("Live Primary Mission Graphs"))
canvas_primary.draw()
canvas_primary.get_tk_widget().grid(row=0, column=0)
primary_graphs_button = ctk.CTkButton(self.tabview.tab("Live Primary Mission Graphs"), text="Start Primary Mission Graphs", command=lambda:primary.plot_primary_graphs())
primary_graphs_button.place(x=850, y=190)
secondary = SecondaryGraphData()
canvas_secondary = FigureCanvasTkAgg(secondary.secondaryfig, self.tabview.tab("Live Secondary Mission Graphs"))
canvas_secondary.draw()
canvas_secondary.get_tk_widget().grid(row=0, column=0)
secondary_graphs_button = ctk.CTkButton(self.tabview.tab("Live Secondary Mission Graphs"), text="Start Secondary Mission Graphs", command=lambda: secondary.plot_secondary_graphs())
secondary_graphs_button.place(x=850, y=190)
我尝试过调整显示每个图表的代码顺序,但只允许我显示最后一段运行的代码。例如,如果primary_graphs_button
这一行在secondary_graphs_button
这一行之后执行,那么这个按钮就能正常显示图表。
我用来创建matplotlib图表的类如下:
class PrimaryGraphData():
def __init__(self) -> None:
self.PRIMARYDATASOURCE = "data.csv"
self.primaryfig, self.primaryaxs = plt.subplots(2, 2)
def animate(self, i):
data = pd.read_csv(self.PRIMARYDATASOURCE)
time = data["Time"]
temp = data["Temperature"]
press = data["Pressure"]
alt = data["Altitude"]
plt.cla()
self.primaryaxs[0, 0].plot(time, temp, "tab:orange")
self.primaryaxs[0, 1].plot(time, press, "tab:green")
self.primaryaxs[1, 0].plot(alt, temp)
self.primaryaxs[1, 1].plot(time, alt, "tab:blue")
def plot_primary_graphs(self):
ani = FuncAnimation(plt.gcf(), func=self.animate, interval=500, frames=50)
plt.tight_layout()
plt.show()
class SecondaryGraphData():
def __init__(self) -> None:
self.SECONDARYDATASOURCE = "data2.csv"
self.secondaryfig, self.secondaryaxs = plt.subplots(2, 2)
def secondaryanimate(self, i):
data = pd.read_csv(self.SECONDARYDATASOURCE)
time = data["Time"]
alt = data["Altitude"]
TVOC = data["TVOC"]
eCO2 = data["eCO2"]
H2 = data["H2"]
Ethanol = data["Ethanol"]
plt.cla()
# Plot subplots
self.secondaryaxs[0, 0].plot(time, TVOC, "tab:green")
self.secondaryaxs[0, 1].plot(alt, eCO2, "tab:green")
self.secondaryaxs[1, 0].plot(alt, H2)
self.secondaryaxs[1, 1].plot(time, Ethanol, "tab:blue")
def plot_secondary_graphs(self):
anisecondary = FuncAnimation(plt.gcf(), func=self.secondaryanimate, interval=500,frames=50)
plt.tight_layout()
plt.show()
1 个回答
1
通过和朋友聊天,我意识到问题出在把图表动画放在一个对象里,这样就需要使用plt.show()这个函数,而正是这个函数导致了空白的主图形。把图表的动画放到函数里,并且把canvas_primary = FigureCanvasTkAgg(primary.primaryfig, self.tabview.tab("Live Primary Mission Graphs"))
也放到那个函数里,就解决了这个问题。
下面是这个函数的完整代码:
def primarygraphdata(primaryview, PRIMARYDATASOURCE):
plt.style.use("dark_background")
plt.rcParams["figure.figsize"] = (16, 10)
# Initialise subplots
primaryfig, primaryaxs = plt.subplots(2, 2)
primaryfig.suptitle("Primary Mission Graphs")
primaryfig.set_facecolor("#2b2b2b")
primaryaxs[0, 0].set_title("Time vs Temperature")
primaryaxs[0, 1].set_title("Time vs Pressure")
primaryaxs[1, 0].set_title("Altitude vs Temperature")
primaryaxs[1, 1].set_title("Time vs Altitude")
def primaryanimate(i):
data = pd.read_csv(PRIMARYDATASOURCE)
time = data["Time"]
temp = data["Temperature"]
press = data["Pressure"]
alt = data["Altitude"]
plt.cla()
# Plot subplots
primaryaxs[0, 0].plot(time, temp, "tab:orange")
primaryaxs[0, 1].plot(time, press, "tab:green")
primaryaxs[1, 0].plot(alt, temp)
primaryaxs[1, 1].plot(time, alt, "tab:blue")
aniprimary = FuncAnimation(primaryfig, func=primaryanimate, interval=500, frames=50, cache_frame_data=False)
plt.tight_layout()
canvas_primary = FigureCanvasTkAgg(primaryfig, primaryview)
canvas_primary.draw()
canvas_primary.get_tk_widget().grid(row=0, column=0)