无法在tkinter窗口中嵌入多个动画matplotlib图表

0 投票
1 回答
31 浏览
提问于 2025-04-14 18:08

当第一次点击“实时次要任务图表”按钮时,次要图表的数据会嵌入到界面中,并且是动态的。不过,这时会生成两个空的主要图形,一个是由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)

撰写回答