【问题标题】:How can I clear or overwrite a tkinter canvas?如何清除或覆盖 tkinter 画布?
【发布时间】:2019-01-22 04:20:39
【问题描述】:

下面的代码显示了我目前正在处理的 tkinter GUI 的一页。

我想要“清除绘图字段”按钮做的就是它所说的:清除画布,因为如果我再次绘图,新的绘图会在下面打包。

或者:我怎样才能覆盖现有的情节,这样我就可以摆脱按钮本身?

class PlotPage(tk.Frame):
"""Page containing the matplotlib graphs"""

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = ttk.Label(self, text="PlotPage", font=LARGE_FONT)
        label.pack(pady=5)

        button1 = ttk.Button(self, text="Back to Start Page", command=lambda: controller.show_frame(StartPage))
        button1.pack(pady=5)

        buttonPlot = ttk.Button(self, text="Show Plot", command=self.plot)
        buttonPlot.pack(pady=5)

        buttonClear = ttk.Button(self, text="Clear Plot Field", command=lambda: controller.show_frame(PlotPage))
        buttonClear.pack(pady=5)

    def plot(self):
    """generate a simple matplotlib graph for multiple profiles"""

        f = Figure(figsize=(8,4), dpi=100)   
        a = f.add_subplot(111)

        for profile in listofProfiles:
            X_list=profile.indexList
            Y_list=profile.VL_List

            [...] Some lines related to plotting [...]

            a.plot(X_list, Y_list, lw=0.3,)

        canvas = FigureCanvasTkAgg(f, self)
        canvas.show()
        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        toolbar = NavigationToolbar2TkAgg(canvas, self)
        toolbar.update()
        canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        print("Stuff has been plotted")

    def clearPlotPage(self):
    """cleares the whole plot field"""     

        # ???

        print("Plot Page has been cleared")

【问题讨论】:

    标签: python matplotlib tkinter


    【解决方案1】:

    只需在谷歌上搜索“clear tkinter canvas”即可获得thisthisthisthis

    简答:调用canvas.delete('all') 将清除整个画布。

    【讨论】:

    • 您可以简单地删除画布并重新创建。
    • 我也找到并尝试了这个,但问题是:清除方法中不存在画布。那么我该如何解决呢?
    • @Tybald 您可以通过添加 self. 作为前缀来使 canvas 成为类属性。这将使您的clearPlotPage(self) 方法能够与self.canvas 一起使用,您可以从那里删除它,然后再次调用self.plot() 重新创建。
    • @Mike-SMT 如果您删除画布,您需要再次重做任何格式或属性设置(假设您已将该信息保存在某处)。根据您使用的管理器,它也可能会弄乱您的布局
    • @en_Knight 如果您使用框架来固定画布,它不会弄乱布局。如果您首先在函数中创建画布,那么只需删除画布并重新运行该函数即可创建它。我的应用程序这样做没有问题。
    【解决方案2】:

    我会 destroy() 画布,然后重新运行 plot()。为此,您需要将canvas 设为类似self.canvas 的类属性。现在我们有了一个类属性,您的任何方法都可以毫无问题地使用self.canvas

    看看我根据你的问题修改的这段代码,如果你有任何问题,请告诉我。

    class PlotPage(tk.Frame):
        def __init__(self, parent, controller):
            tk.Frame.__init__(self, parent)
    
            self.canvas = None
    
            label = ttk.Label(self, text="PlotPage", font=LARGE_FONT)
            label.pack(pady=5)
            button1 = ttk.Button(self, text="Back to Start Page", command=lambda: controller.show_frame(StartPage))
            button1.pack(pady=5)
            buttonPlot = ttk.Button(self, text="Show Plot", command=self.plot)
            buttonPlot.pack(pady=5)
            buttonClear = ttk.Button(self, text="Clear Plot Field", command=lambda: controller.show_frame(PlotPage))
            buttonClear.pack(pady=5)
    
        def plot(self):
            if self.canvas == None:
                f = Figure(figsize=(8,4), dpi=100)   
                a = f.add_subplot(111)
    
                for profile in listofProfiles:
                    X_list=profile.indexList
                    Y_list=profile.VL_List
                    # [...] Some lines related to plotting [...]
                    a.plot(X_list, Y_list, lw=0.3,)
    
                self.canvas = FigureCanvasTkAgg(f, self)
                self.canvas.show()
                self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
    
                toolbar = NavigationToolbar2TkAgg(self.canvas, self)
                toolbar.update()
                self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
    
                print("Stuff has been plotted")
            else:
                print("Plot already plotted please clear first")
    
        def clearPlotPage(self):
            self.canvas.destroy()
            self.canvas = None
            self.plot()
            print("Plot Page has been cleared")
    

    【讨论】:

    • 嗨迈克,我确定这个解决方案有效,我只是想知道破坏画布然后重建它而不是使用删除有什么好处?如果您使用的是依赖于订单的管理器(或者如果用户手动调整了某些小部件的大小),并且如果您以非常高的频率运行它,那么缺点似乎是您的布局可能难以重新创建的风险您可能会看到小部件跳来跳去,试图快速调整大小
    • @en_Knight 这取决于目标。对于像按钮这样的简单刷新,只要您的画布在框架内,就应该没有问题。对于更高的容量,您可以使用 matplotlib 的更新方法。就像清除情节/子情节然后重新绘制一样。
    • @Mike-SMT 我了解了类变量是什么以及它为什么有意义。这很好,但显然destroy() 不存在:AttributeError: 'FigureCanvasTkAgg' object has no attribute 'destroy' 所以我真的不知道如何继续。也没有我觉得有点混乱的 delete()clear() 方法。
    【解决方案3】:

    对于仍在处理 AttributeError 的任何人:“FigureCanvasTkAgg”对象没有“destroy”属性。

    我通过创建一个“虚拟”容器框架来包装可以被破坏的 FigureCanvas 来解决这个问题,进而破坏 FigureCanvas。

    【讨论】:

      猜你喜欢
      • 2013-03-28
      • 1970-01-01
      • 1970-01-01
      • 2015-07-17
      • 1970-01-01
      • 1970-01-01
      • 2012-02-15
      • 2020-11-30
      • 1970-01-01
      相关资源
      最近更新 更多