I have several graphs that I want to display on a button press. To do that, I make the plt.Figure
and FigureCanvasTkAgg
variables global, and just erase the axis each time on button press with ax.clear()
. After that, i added a feature using Figure.canvas.mpl_connect
: when I press on the graph area, the second point is highlighted with a vertical line. When I print some simple output (in my case, print('Vertical Line Constructed')
in the select_trade_with_mouse
function), it turns out that the event is created for each graph that was constructed and erased: when I generate a graph and press on graph (that generates event), then the print('Vertical Line Constructed')
is executed just once. If I generate the second graph and click on graph, then the print('Vertical Line Constructed')
is executed twice. Looks like the old graphs aren't destroyed, and the click on graph generates an event for each graph in memory, even if it is not displayed. I tried plt.cla()
, plt.clf()
and plt.close()
, but none of them completely removes the graph.
My question is, how can I properly remove the old graphs? So that a click on graph will generate only one event?
My code:
import pandas as pd
import tkinter as tk
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
def select_trade_with_mouse(event, ax, graph, data):
global vertical_line_trading
print('Vertical Line Constructed')
if vertical_line_trading:
vertical_line_trading.remove()
del vertical_line_trading
vertical_line_trading = ax.axvline(data, color='b')
graph.draw()
def construct_graph(change_by = 0):
global data
global graph_index
print('Graph Constructed')
graph_index = graph_index + change_by
ax.clear()
#plt.close('all')
line = data[graph_index].plot(x='x', y='y', linestyle='-', ax=ax, linewidth=1, color='y')
click_id = figure.canvas.mpl_connect('button_press_event', lambda event: select_trade_with_mouse(event, ax, graph, data[graph_index].loc[1, 'x']))
graph.draw()
if __name__ == '__main__':
vertical_line_trading = None
graph_index = 0
## Some random data
data = []
for i in range(10):
data.append(pd.DataFrame({'x': [1+i, 2+i, 3+2*i], 'y': [1+2*i, 2+i, 3+i]}))
root = tk.Tk()
main_frame = tk.Frame(root, height=600, width=1200)
graph_frame = tk.Frame(main_frame, height=500, width=1200)
## Graph
figure = plt.Figure(figsize=(10,10), dpi=100)
ax = figure.add_subplot(111)
graph = FigureCanvasTkAgg(figure, graph_frame)
graph.get_tk_widget().pack(side=tk.LEFT)
## Buttons to switch between graphs
prev_graph_button = tk.Button(graph_frame, command = lambda: construct_graph(-1), height=10, width=10, text='Prev\nGraph')
next_graph_button = tk.Button(graph_frame, command = lambda: construct_graph(1), height=10, width=10, text='Next\nGraph')
prev_graph_button.pack(side=tk.LEFT)
next_graph_button.pack(side=tk.LEFT)
for frame in [main_frame, graph_frame]:
frame.pack(side=tk.BOTTOM, fill='both')
frame.pack_propagate(0)
root.mainloop()
You don't have to remove graph. You have to use mpl_connect()
only once at start, and not again and again when you clear graph.
Or you have to keep click_id
in global variable and use mpl_disconnect(click_id)
before click_id = mpl_connect()
I create global variable click_id = None
at start and later in construct_graph()
I remove previous click_id
if it is not None
. This way graph has assigned only one function
import pandas as pd
import tkinter as tk
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
def select_trade_with_mouse(event, ax, graph, data):
global vertical_line_trading
print('Vertical Line Constructed')
if vertical_line_trading:
vertical_line_trading.remove()
del vertical_line_trading
vertical_line_trading = ax.axvline(data, color='b')
graph.draw()
def construct_graph(change_by = 0):
global data
global graph_index
global click_id
print('Graph Constructed')
graph_index = graph_index + change_by
ax.clear()
#plt.close('all')
line = data[graph_index].plot(x='x', y='y', linestyle='-', ax=ax, linewidth=1, color='y')
# if function exist then remove it
if click_id: # if click_id is not None:
figure.canvas.mpl_disconnect(click_id)
click_id = figure.canvas.mpl_connect('button_press_event', lambda event: select_trade_with_mouse(event, ax, graph, data[graph_index].loc[1, 'x']))
graph.draw()
if __name__ == '__main__':
click_id = None # create global varaible with default value at start
vertical_line_trading = None
graph_index = 0
## Some random data
data = []
for i in range(10):
data.append(pd.DataFrame({'x': [1+i, 2+i, 3+2*i], 'y': [1+2*i, 2+i, 3+i]}))
root = tk.Tk()
main_frame = tk.Frame(root, height=600, width=1200)
graph_frame = tk.Frame(main_frame, height=500, width=1200)
## Graph
figure = plt.Figure(figsize=(10,10), dpi=100)
ax = figure.add_subplot(111)
graph = FigureCanvasTkAgg(figure, graph_frame)
graph.get_tk_widget().pack(side=tk.LEFT)
## Buttons to switch between graphs
prev_graph_button = tk.Button(graph_frame, command = lambda: construct_graph(-1), height=10, width=10, text='Prev\nGraph')
next_graph_button = tk.Button(graph_frame, command = lambda: construct_graph(1), height=10, width=10, text='Next\nGraph')
prev_graph_button.pack(side=tk.LEFT)
next_graph_button.pack(side=tk.LEFT)
for frame in [main_frame, graph_frame]:
frame.pack(side=tk.BOTTOM, fill='both')
frame.pack_propagate(0)
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.