简体   繁体   English

如何从 Tkinter 中的 matplotlib 中删除/清除子图和 canvas(白色窗口-FigureCanvasTkAgg)?

[英]How to remove/clear the subplot and canvas (white window- FigureCanvasTkAgg) from matplotlib in Tkinter?

I'm trying to run a gui where I'm providing two buttons.我正在尝试运行一个提供两个按钮的 gui。 1st one to print content of the file 'names.txt' and 2nd is to plot the data.第一个打印文件“names.txt”的内容,第二个是 plot 数据。 However, if I'm plotting data first and then going to print the content, the subplot is remaining as it is and I'm unable to clear it.但是,如果我先绘制数据然后再打印内容,则子图将保持原样,我无法清除它。 Here is my output: [:[wrong_output][1]]1 I read the post : Clear figure subplots matplotlib python and tried the same, however I'm not getting correct output And the subplot is not destroying. Here is my output: [:[wrong_output][1]]1 I read the post : Clear figure subplots matplotlib python and tried the same, however I'm not getting correct output And the subplot is not destroying. I even tried to destroy the widget using self.scatter1.get_tk_widget().destroy() but this isnt working either Can someone please tell me how to proceed?我什至尝试使用self.scatter1.get_tk_widget().destroy() destroy小部件,但这也不起作用有人可以告诉我如何继续吗? My code is:我的代码是:

import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import random

x_loc=[5, 6, 34, 54, 23]
y_loc=[3, 4.34, 2, 44, 65]
avgLst=[24, 35.65, 54.6, 53, 2]
root= tk.Tk()

class graph_plot():
    global graph_past
    global graph_Avg
    
    def __init__(self):
        self.figure1 = plt.Figure()
        self.scatter1 = FigureCanvasTkAgg(self.figure1, root)
        self.scatter1.get_tk_widget().place(relx= 0.5, rely=0.1)
        self.subplot1 = self.figure1.add_subplot(111)
        self.subplot1.set_xlabel('x location')
        self.subplot1.set_ylabel('y location')
        
        
    def display_graph(self):
        data1 = {'x-locations' : x_loc , 'y_locations' : y_loc}
        df3 = DataFrame(data1,columns=['x-locations','y_locations'])
        global graph_past
        label2.config(text='')
        print('graph in= ' , graph_past)
        im0= self.subplot1.scatter(df3['x-locations'],df3['y_locations'], c=avgLst, cmap='rainbow', vmin=min(avgLst), vmax=max(avgLst))
        self.figure1.colorbar(im0)
        self.subplot1.set_title('Avg')
        graph_past= True
            
    def clear_graph(self):
        print('Destroyed!')
        self.subplot1.clear
        ## ??? which command


def do_graph():
    obj1 = graph_plot()
    obj1.display_graph()
   
def on_key(event):
    if myLine and event.keysym != 'Return':
        update_print()

def do_printing():
    global myLine
    global graph_past
    #print('graph_past= ' , graph_past)
    if graph_past:
        obj2 = graph_plot()
        obj2.clear_graph()
    graph_past = False
    input_File = open('names.txt','r')
    myLine = input_File.readlines()
    update_print()
    
def update_print():
    label2.config(text=random.choice(myLine))
  
def flag_print():
    global graph_Avg
    graph_Avg=False
    do_printing()

def flag_Avg():
    global graph_Avg
    graph_Avg=True
    do_graph()

root.bind('<Key>', on_key)

myCanvas = tk.Canvas(root, width = 800, height = 500)
myCanvas.grid(row=2, column= 4)

label1 = tk.Label(root, text='MENU')
label1.config(font=('Arial', 20))
myCanvas.create_window(200, 20, window=label1)
myLine= None
graph_Avg=False
graph_past=False

label2 = tk.Label(root, font=('Courier', 15))
label2.place(relx= 0.3, rely=0.1)

B1 = tk.Button(root, text ="Option 1", font=('Courier', 12), command = flag_print)
myCanvas.create_window(200, 100, window=B1)

B2 = tk.Button(root, text ="Option 2", font=('Courier', 12), command = flag_Avg)
myCanvas.create_window(200, 140, window=B2)

root.mainloop()```


  [1]: https://i.stack.imgur.com/RgL7S.png

Try self.subplot1.clear() in the place of self.subplot1.destroy()尝试self.subplot1.clear()代替self.subplot1.destroy()

Problem问题

The problem is due to creating multiple FigureCanvasTkAgg objects in the __init__() method of the graph_plot class.问题是由于在graph_plot class 的__init__()方法中创建了多个FigureCanvasTkAgg对象。 this constructor is called in the do_graph() and do_printing() methods which means many of the same canvas are being created on top of one another.这个构造函数在do_graph()do_printing()方法中被调用,这意味着许多相同的 canvas 是在彼此之上创建的。 This means when you .destroy() the widget it will be destroying a new one and leaving the one underneath.这意味着当您.destroy()小部件时,它将销毁一个新的小部件并将其留在下面。

Solution解决方案

The solution would be to hoist more variables up into global variables if you're going to continue using classes and that way you'll be ensured you're handling the same objects, not separate ones.如果您要继续使用类,解决方案是将更多变量提升到全局变量中,这样您就可以确保您处理的是相同的对象,而不是单独的对象。 It might be best to rethink the use of classes for this problem entirely though.不过,最好重新考虑完全使用类来解决这个问题。

Code I restructured some of your code to eschew classes and achieve the desired results:代码我重组了您的一些代码以避开类并达到预期的结果:

import tkinter as tk
import matplotlib.pyplot as plt
from pandas import DataFrame
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import random

x_loc=[5, 6, 34, 54, 23]
y_loc=[3, 4.34, 2, 44, 65]
avgLst=[24, 35.65, 54.6, 53, 2]

GRAPH_AVG=False
GRAPH_PAST=False
MY_LINE = None


ROOT = tk.Tk()
ROOT.geometry("900x600")
FIGURE = plt.Figure()
SCATTER = FigureCanvasTkAgg(FIGURE, ROOT)

TK_WIDGET = SCATTER.get_tk_widget()

SUBPLOT = FIGURE.add_subplot(111)
SUBPLOT.set_xlabel('x location')
SUBPLOT.set_ylabel('y location')

NAME_LABEL = tk.Label(ROOT, font=('Courier', 15))
NAME_LABEL.place(relx=0.3, rely=0.1)
        
def display_graph():
    global GRAPH_PAST, FIGURE, SUBPLOT

    data1 = {'x-locations' : x_loc , 'y_locations' : y_loc}
    df3 = DataFrame(data1, columns=['x-locations','y_locations'])
    NAME_LABEL.config(text='')
    print('graph past= ' , GRAPH_PAST)
    im0= SUBPLOT.scatter(df3['x-locations'],df3['y_locations'], c=avgLst, cmap='rainbow', vmin=min(avgLst), vmax=max(avgLst))
    FIGURE.colorbar(im0)
    SUBPLOT.set_title('Avg')
    TK_WIDGET.place(relx=0.3, rely=0.1)
    GRAPH_PAST= True
        
def clear_graph():
    global SUBPLOT, TK_WIDGET
    print('Destroyed!')
    SUBPLOT.clear()
    TK_WIDGET.place_forget()

   
def on_key(event):
    global MY_LINE
    if MY_LINE and event.keysym != 'Return':
        update_print()

def do_printing():
    global MY_LINE, GRAPH_AVG, GRAPH_PAST

    if GRAPH_PAST:
        clear_graph()
    GRAPH_PAST = False
    MY_LINE = ["john kenny", "maria rose", "sheena"]
    update_print()
    
def update_print():
    NAME_LABEL.config(text=random.choice(MY_LINE))
  
def flag_print():
    global GRAPH_AVG
    GRAPH_AVG=False
    do_printing()

def flag_Avg():
    global GRAPH_AVG
    GRAPH_AVG=True
    display_graph()


ROOT.bind('<Key>', on_key)

B1 = tk.Button(ROOT, text ="Print", font=('Courier', 12), command=flag_print)
B1.place(relx=0.1, rely=0.1)

B2 = tk.Button(ROOT, text ="Graph", font=('Courier', 12), command=flag_Avg)
B2.place(relx=0.1, rely=0.2)

ROOT.mainloop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM