I have a PySimpleGUI window that contains a Matplotlib bar graph. I recently added an event to it that allows the user to click a bar and access a function based on the bar's label. This works great... until I follow up with a click in a non-matplotlib area, such as my PSG buttons. After doing some testing, it appears that this issue only happens if I call a new, different, window function as a result of the on_click event function running. In my example here, if I remove another_window(), I don't have an issue click-printing the names of my bars or hitting buttons in PSG. The problem is that I need to trigger other windows and be able to return to a functioning main window. What am I doing incorrectly? Thanks in advance!
import PySimpleGUI as sg
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib import pyplot as plt
from matplotlib.backend_bases import MouseButton
class Toolbar(NavigationToolbar2Tk):
def __init__(self, *args, **kwargs):
super(Toolbar, self).__init__(*args, **kwargs)
def on_click(event):
ax = event.inaxes
x = event.xdata
lbls = ax.get_xticklabels()
idx = int(x.round())
lbl = lbls[idx]
print('bar name is ', lbl.get_text())
another_window()
def draw_figure(canvas, figure, canvas_toolbar, loc=(0, 0)):
if canvas.children:
for child in canvas.winfo_children():
child.destroy()
if canvas_toolbar.children:
for child in canvas_toolbar.winfo_children():
child.destroy()
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
toolbar = Toolbar(figure_canvas_agg, canvas_toolbar)
toolbar.update()
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
def data():
fig, ax = plt.subplots(figsize=(20,9), dpi=100)
width = 0.95
ax.tick_params(axis='x', labelrotation = 90, labelright=True)
ax.set_ylabel('Stock Quantity')
for x in range(5):
bar_name = x
bar_qty = x
ax.bar(bar_name, bar_qty, width, color='red', label='Quantity')
plt.subplots_adjust(top = 1, bottom = .15, right = 1, left = .03, hspace = 0, wspace = 0)
plt.margins(0,0)
plt.margins(x=0)
return fig
def another_window():
layout = [[sg.T('Hello')]]
window = sg.Window(layout=layout, title='', size=(100,100))
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit':
window.Close()
break
def main():
team_buttons = [[sg.T('Options', text_color='black', font = 'Arial 18')],
[sg.Button('Store Inventory', size = (17,1), font = 'Arial 14', k='-STORE BUTTON1-'),
sg.Button('Retrieve Inventory', size = (17,1), font = 'Arial 14', k='-RETRIEVE BUTTON1-'),
sg.Button('Exit', button_color = '#36454f', size = (17,1), font = 'Arial 14', k='-EXIT BUTTON1-')]]
layoutMain = [[sg.Canvas(key=('-controls_cv-'))],
[sg.Column(team_buttons, visible=True),],
[sg.Canvas(size=(1920, 800), pad=((0,0),(0,0)), key='-CANVAS-', expand_x = True, expand_y = False, border_width = 50)]]
windowMain = sg.Window('E-Stock', layoutMain, no_titlebar=False, size=(1920,1080), finalize=True, resizable=True)
windowMain.maximize()
fig = data()
fig_photo = draw_figure(windowMain['-CANVAS-'].TKCanvas, fig, windowMain['-controls_cv-'].TKCanvas)
cid = fig.canvas.mpl_connect('button_press_event', on_click)
while True:
event, values = windowMain.read()
if event == '-STORE BUTTON1-':
print('store part')
if event == '-RETRIEVE BUTTON1-':
print('retrieve part')
if event == sg.WIN_CLOSED or event == 'Exit' or event == '-EXIT BUTTON1-':
windowMain.Close()
break
main()
CodePudding user response:
Not sure what's wrong about fig.canvas.mpl_connect
.
My suggestion is not create a new window in the event handler, but generate an event to main_window for new window.
def on_click(event, win):
ax = event.inaxes
x = event.xdata
lbls = ax.get_xticklabels()
idx = int(x.round())
lbl = lbls[idx]
print('bar name is ', lbl.get_text())
win.write_event_value('Another', None)
cid = fig.canvas.mpl_connect('button_press_event', lambda event, win=windowMain:on_click(event, win))
while True:
event, values = windowMain.read()
if event == '-STORE BUTTON1-':
print('store part')
if event == '-RETRIEVE BUTTON1-':
print('retrieve part')
if event == sg.WIN_CLOSED or event == 'Exit' or event == '-EXIT BUTTON1-':
windowMain.Close()
break
elif event == 'Another':
another_window()