如何清除 tkinter 中的 matplotlib 图?

How do I clear a mathplotlib graph in tkinter?

我正在尝试清除 tkinker 中的(整个)mathplotlib 图。意思是,我正在尝试绘制图 A。单击清除按钮。单击清除按钮后,我的目标是从 canvas 中清除图 A。如果我点击按钮 plot graph B,就会出现 graph B 的内容。目前,当我尝试清除图形(单击清除图形按钮)时,我看到 AttributeError: 'GetInterfaceValues' object has no attribute 'canvas'。有人可以引导我朝着正确的方向前进吗?

基本上这是我的代码: plotting.py 文件

    import matplotlib
    import pandas as pd
    matplotlib.use("TkAgg")
    import matplotlib.pyplot as plt
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

    fig, ax = plt.subplots()


    def plotGraph(self):
        df = pd.DataFrame({'Years': ['2016-12-31', '2017-12-31', '2018-12-31', '2019-12-31'],
                           'Value': [-495982.0, -405549.0, -351541.0, -283790.0]})

        yLabelText = "Value"
        ax.set_xlabel('Years')
        ax.set_ylabel(yLabelText)

        fig = plt.figure(figsize=(12, 10), dpi=80)
        ax1 = fig.add_subplot(111)
        ax1.set_title('Keg values')
        ax1.set_xlabel('Years')
        ax1.set_ylabel(yLabelText)

        datas = df.plot(ax=ax1, color ='orange')
        ax.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))
        fig.tight_layout()
        canvas = FigureCanvasTkAgg(fig, self)
        canvas.draw()
        canvas.get_tk_widget().pack(side="bottom", fill="both", expand=True)


    def plotCashGraph(self):
        df = pd.DataFrame({'Quarter': ['2018-03-31', '2018-06-30', '2018-10-31', '2020-01-01'],
                           'Value': [-9000.0, 105549.0, -51541.0, 2790.0]})


        yLabelText = "Value"
        ax.set_xlabel('Quarter')
        ax.set_ylabel(yLabelText)

        fig = plt.figure(figsize=(12, 10), dpi=80)
        ax1 = fig.add_subplot(111)
        ax1.set_title('Cash')
        ax1.set_xlabel('Quarter')
        ax1.set_ylabel(yLabelText)

        datas = df.plot(ax=ax1, color ='green')
        ax.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))
        fig.tight_layout()
        canvas = FigureCanvasTkAgg(fig, self)
        canvas.draw()
        canvas.get_tk_widget().pack(side="bottom", fill="both", expand=True)


    def clearPlotPage(self):
            self.canvas.destroy()
            self.canvas = None

和接口文件:

    try:
        import Tkinter as tk
    except:
        import tkinter as tk

    import plotting as pyt


    class GetInterfaceValues():
        def __init__(self):
            self.root = tk.Tk()
            self.totalValue = tk.StringVar()

            self.root.geometry('900x500')

            self.plotGraphButton = tk.Button(self.root, text='plot the kegs values', command=self.plotKeg)
            self.plotCashValue = tk.Button(self.root, text='plot cash value', command=self.plotCash)

            self.clearButton = tk.Button(self.root,text='Clear Chart',command=self.clear)

            self.plotGraphButton.pack()
            self.plotCashValue.pack()
            self.clearButton.pack()

            self.root.mainloop()



        def plotKeg(self):
            pyt.plotGraph(self.root)

        def plotCash(self):
            pyt.plotCashGraph(self.root)


        def clear(self):
            pyt.clearPlotPage(self)




    app = GetInterfaceValues()

几件事:

  1. 奇怪的是,当您不使用 class 时,您的函数接受 self 作为参数。我想您最初是从 OOP 方法复制代码的。
  2. 您不必删除 canvas 并重新创建它。您可以简单地重复使用它。
  3. fig也是如此——你只需要清除它并重新绘制。

从您的 plotting.py 开始,我建议您创建 class 并改为创建 class 方法:

import matplotlib
import pandas as pd

matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure #as said before, use Figure instead of pyplot

class PlotGraph:
    def __init__(self):
        self.canvas = None
        self.fig = Figure(figsize=(12, 10), dpi=80)

    def plotGraph(self, container):
        df = pd.DataFrame({'Years': ['2016-12-31', '2017-12-31', '2018-12-31', '2019-12-31'],
                           'Value': [-495982.0, -405549.0, -351541.0, -283790.0]})
        ax = self.fig.add_subplot(111)
        ax.set_title('Keg values')
        ax.set_xlabel('Years')
        ax.set_ylabel("Value")
        ax.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))
        df.plot(ax=ax, color='orange')
        if not self.canvas:
            self.canvas = FigureCanvasTkAgg(self.fig, container)
            self.canvas.get_tk_widget().pack(side="bottom", fill="both", expand=True)
        self.canvas.draw_idle()

    def plotCashGraph(self, container):
        df = pd.DataFrame({'Quarter': ['2018-03-31', '2018-06-30', '2018-10-31', '2020-01-01'],
                           'Value': [-9000.0, 105549.0, -51541.0, 2790.0]})
        ax = self.fig.add_subplot(111)
        ax.set_xlabel('Quarter')
        ax.set_ylabel("Value")
        ax.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))
        df.plot(ax=ax, color='green')
        if not self.canvas:
            self.canvas = FigureCanvasTkAgg(self.fig, container)
            self.canvas.get_tk_widget().pack(side="bottom", fill="both", expand=True)
        self.canvas.draw_idle()

    def clearPlotPage(self):
        self.fig.clear() #clear your figure
        self.canvas.draw_idle() #redraw your canvas so it becomes empty

设置好后端后,只需稍微修改一下接口文件即可:

try:
    import Tkinter as tk
except:
    import tkinter as tk

import plotting as pyt

class GetInterfaceValues():
    def __init__(self):
        self.root = tk.Tk()
        self.totalValue = tk.StringVar()

        self.root.geometry('900x500')

        self.plotGraphButton = tk.Button(self.root, text='plot the kegs values', command=self.plotKeg)
        self.plotCashValue = tk.Button(self.root, text='plot cash value', command=self.plotCash)

        self.clearButton = tk.Button(self.root, text='Clear Chart', command=self.clear)

        self.plotGraphButton.pack()
        self.plotCashValue.pack()
        self.clearButton.pack()

        self.root.mainloop()

    def plotKeg(self):
        plot.plotGraph(self.root)

    def plotCash(self):
        plot.plotCashGraph(self.root)

    def clear(self):
        plot.clearPlotPage()

plot = pyt.PlotGraph() #initiate a class instance
app = GetInterfaceValues()