简体   繁体   中英

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. 1st one to print content of the file 'names.txt' and 2nd is to plot the data. 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. 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? 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()

Problem

The problem is due to creating multiple FigureCanvasTkAgg objects in the __init__() method of the graph_plot class. 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. This means when you .destroy() the widget it will be destroying a new one and leaving the one underneath.

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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