VPython version: 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]
port: tkinter
tkinter version: 8.6.9
PySimpleGUI version: 4.60.4
Have used another Python GUI Framework? (tkinter, Qt, etc) (yes/no is fine)
These items may solve your problem. Please check those you've done by changing - [ ] to - [X]
While developing any Matplotlib toolbar integrated GUI with PysmpleGUI the application gets collapsed on selecting any GUI element with the toolbar being selected refer the below small video for refference
i am not sure how to solve this issue though i am very close to fining the solution
@jason990420
and
@PySimpleGUI
your help is very much required
import PySimpleGUI as sg
import numpy as np
Embedding the Matplotlib toolbar into your application
# ------------------------------- This is to include a matplotlib figure in a Tkinter canvas
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
def draw_figure_w_toolbar(canvas, fig, canvas_toolbar):
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(fig, master=canvas)
figure_canvas_agg.draw()
toolbar = Toolbar(figure_canvas_agg, canvas_toolbar)
# toolbar.toggle()
# toggle_tooloff(toolbar._actions[str(fig.canvas.toolbar.mode)])
toolbar.update()
figure_canvas_agg.get_tk_widget().pack(side='right', fill='both', expand=1)
class Toolbar(NavigationToolbar2Tk):
def __init__(self, *args, **kwargs):
super(Toolbar, self).__init__(*args, **kwargs)
# ------------------------------- PySimpleGUI CODE
layout = [
[sg.T('Graph: y=sin(x)')],
[sg.B('Plot'), sg.B('Exit')],
[sg.T('Controls:')],
[sg.Canvas(key='controls_cv')],
[sg.T('Figure:')],
[sg.Column(
layout=[
[sg.Canvas(key='fig_cv',
# it's important that you set this size
size=(400 * 2, 400)
background_color='#DAE0E6',
pad=(0, 0)
[sg.B('Alive?')]
window = sg.Window('Graph with controls', layout)
while True:
event, values = window.read()
print(event, values)
if event in (sg.WIN_CLOSED, 'Exit'): # always, always give a way out!
break
elif event is 'Plot':
# ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE
plt.figure(1)
fig = plt.gcf()
DPI = fig.get_dpi()
# ------------------------------- you have to play with this size to reduce the movement error when the mouse hovers over the figure, it's close to canvas size
fig.set_size_inches(404 * 2 / float(DPI), 404 / float(DPI))
# -------------------------------
x = np.linspace(0, 2 * np.pi)
y = np.sin(x)
plt.plot(x, y)
plt.title('y=sin(x)')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid()
# ------------------------------- Instead of plt.show()
draw_figure_w_toolbar(window['fig_cv'].TKCanvas, fig, window['controls_cv'].TKCanvas)
window.close()
@jason990420 or @PySimpleGUI i have done some research and found that there is a possible way to toggle the selection with toggle_tooloff() but seems its not available or iam not sure why its throwing me an error
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk
fig, ax = plt.subplots()
canvas = fig.canvas
# Create a NavigationToolbar2Tk instance
toolbar = NavigationToolbar2Tk(canvas, root)
# Add the toolbar to the Tkinter window
toolbar.pack(side="top", fill="both")
# Toggle the toolbar off
toolbar.toolmanager.toggle_tooloff(toolbar._actions['pan'])
# Update the toolbar
toolbar.update()
using NavigationToolbar2
import matplotlib.pyplot as plt
from matplotlib.backend_bases import NavigationToolbar2
fig, ax = plt.subplots()
# Get the toolbar instance from the figure canvas
toolbar = NavigationToolbar2(fig.canvas)
# Toggle off the currently selected tool in the toolbar
toolbar.toggle()
# Update the canvas to reflect the toolbar changes
fig.canvas.draw_idle()
I don't like to destroy old canvas before redraw new figure again and again.
Following demo the way I create the canvas for figure and toolbar just once.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import PySimpleGUI as sg
layout = [
[sg.T('Graph: y=sin(x)')],
[sg.B('Plot'), sg.B('Exit')],
[sg.T('Controls:')],
[sg.Canvas(key='controls_cv')],
[sg.T('Figure:')],
[sg.Column(layout=[[sg.Canvas(key='fig_cv', size=(400 * 2, 400))]], background_color='#DAE0E6', pad=(0, 0))],
[sg.B('Alive?')]
window = sg.Window('Graph with controls', layout, finalize=True)
# Initialization for the matplotlib figure
plt.figure(1)
fig = plt.gcf()
DPI = fig.get_dpi()
fig.set_size_inches(404 * 2 / float(DPI), 404 / float(DPI))
canvas = window['fig_cv'].TKCanvas
figure_canvas_agg = FigureCanvasTkAgg(fig, master=canvas)
figure_canvas_agg.get_tk_widget().pack(side='right', fill='both', expand=1)
canvas_toolbar = window['controls_cv'].TKCanvas
toolbar = NavigationToolbar2Tk(figure_canvas_agg, canvas_toolbar)
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, 'Exit'):
break
elif event == 'Plot':
plt.clf()
x = np.linspace(0, 2 * np.pi)
y = np.sin(x)
plt.plot(x, y)
plt.title('y=sin(x)')
plt.xlabel('X')
plt.ylabel('Y')
plt.grid()
figure_canvas_agg.draw()
toolbar.update()
window.close()
Thats a nice approach which I tried prior but I am not sure why my plots are not being plotted it should be a silly mistake i could have made but i couldn't figure (where i am going wrong. maybe its because I have my subplots growing based on the selected checkbox where i delete all the axes and replot it)
i am getting an error when i try to do toolbar.update()
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: invalid command name ".!toplevel.!frame2.!labelframe.!frame.!canvas.!navigationtoolbar2tk.!button2"
and when I try to display my plot using "figure_canvas_agg.draw()" nothing happens
If you don't mind i can add you as a collaborator to my repo can you help me fix this issue
as i can't share the code here nor I couldn't even create any minimal code replica as i could not figure where the issue is
your help is much appreciated
@jason990420 inviting to collaborate on my repo, Note my account is not a organization/Enterprise account there by you should have all access to my repo.
I know this is not a best practice but your contribution to this community is very extensive which made me feel ok on my decision
Thereby requesting to accept my collaboration invite and you will have the refactored code in https://github.com/Darksoulz15/auto_plot_Pavan/tree/GraphUpdateBug
Its very important for me that these data or codes should be very private
FYI: @Techmaniac154 belongs to me
thank you