Potentially unintended behavior when integrating with tkinter

I would not catalogue this as a bug, but more as “unintended behavior”. First, let me put you into context:

Let’s say, I want to create a matplotlib chart, embedded in a tkinter window. Therefore, I will be using tools like FigureCanvasTkAgg and NavigationToolbar2Tk.

Then, I want to edit the NavigationToolbar2Tk. I will remove buttons this way:

self.toolbar.children['!button4'].pack_forget()
self.toolbar.children['!checkbutton1'].pack_forget()
self.toolbar.children['!frame'].pack_forget()
self.toolbar.children['!frame2'].pack_forget()

Then, I will create some Buttons and Checkbuttons, and add them by packing. I will also use the method self.toolbar._Spacer() to add some Spacers.

All of these WORKS fine. The problem is: let’s now do the following. All the chart is being created in a custom class object (that’s why you see me using self). Now, I will delete the class, and start the process again. When running line self.toolbar.children['!checkbutton1'].pack_forget(), I will get an error. That one is the only pack_forget() triggering it. The reason is, the new toolbar has the same children as before when initialised, except for checkbuttons - their numbers will change, but why?

Consider that “delete the class” does not involve stopping the code. I have a Tk() window with a button, and matplotlib plots in a Toplevel() window. I close the Toplevel window, and press a button in my Tk() to create the new Toplevel and custom class with my matplotlib stuff.

I’ll give you a photo of two prints. They are printing all keys of self.toolbar.children, for the first try (no errors) and the second (triggers error)

I think we need a minimal reproducer as I suspect that this is going to involve details of Tk and the exact lifetime of your objects (I’m also not sure that those names are stable as I see names like '!checkbutton-1'). I think that it is Tk generating those string labels, we also need to sort out exactly what level is responsible for generating and incrementing those counters.

However, if you goal is to always remove some of the buttons I suggest you sub-class NavigationToolbar2Tk and override toolitems to only include the buttons you want (see matplotlib/lib/matplotlib/backend_bases.py at a833d99e46f5771aee7c25066276a70e6e7b9ef3 · matplotlib/matplotlib · GitHub for the default list, copy-paste-delete that in your class). This will sidestep sorting out exactly with tk is doing here :slight_smile: .