0

I am creating an application which will display a number of charts using pd.plot displayed within a Tkinter user interface. Since I'm displaying multiple charts within the same window, I want a scrollbar. The code below seems to work fine, except when the Tkinter TopLevel window is closed, I get the following error:

_tkinter.TclError: invalid command name ".!toplevel.!scrollbar"

Otherwise, everything is working as expected. I can't seem to find a similar problem anywhere on the interwebs. Below is a MRE that produces my error:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from tkinter import *
from tkinter import ttk

class TestClass(Frame):
    def __init__(self, parent=None):
        self.parent = parent
        Frame.__init__(self)
        self.main = self.master
        #Display graphs
        g_top = Toplevel(bg='white')
        g_top.title('Charts that create error :(')
        x = 5
        y = 5
        h = 800
        w = 1100
        g_top.geometry('%dx%d+%d+%d' % (w, h, x, y))

        g_scroll = Scrollbar(g_top, orient='vertical')
        g_scroll.pack(side='right', fill='y')

        can=Canvas(g_top, yscrollcommand=g_scroll.set)
        can.pack(side='left', fill='both', expand=True)
        g_scroll.config(command=can.yview)

        frm = Frame(can)
        can.create_window((4,4), window=frm, anchor='nw')
        frm.bind('<Configure>', 
                lambda event, canvas=can: self.onFrameConfigure(canvas))

        fs = (12,30)
        dpi = 100

        fig, axes = plt.subplots(nrows=3, ncols=1, figsize=fs, dpi=dpi)
        chart_type = FigureCanvasTkAgg(fig, frm)
        chart_type.get_tk_widget().grid(column=0, row=0)
        fig.tight_layout(pad=1.1)
        fig.subplots_adjust(bottom=0.2, hspace=0.2)

        df=pd.DataFrame(np.random.randn(5, 2), columns=['A','B'])
        df.plot(kind='bar', ax=axes[0], width=0.8)
        df.plot(kind='line', ax=axes[1])
        df.plot(kind='scatter', x='A', y='B', ax=axes[2])

    def onFrameConfigure(self, canvas):
        #Fixes scrollbar on tkinter canvas
        canvas.configure(scrollregion=canvas.bbox("all"))

if __name__ == '__main__':
    root=Tk()
    ui = TestClass(root)
    ui.pack()
    root.mainloop()

Thanks!

Tom
  • 1,003
  • 2
  • 13
  • 25
  • Yes! Although I don't know how I would have found this solution based on the error message I was getting. – Tom Nov 29 '19 at 21:35
  • For anyone else who finds this question, here's the specific part of the code I changed to make it work. Remove `import matplotlib.pyplot as plt`, add `from matplotlib.figure import Figure`. Then change the line where `fig, axes` are defined to two different lines: `fig = Figure(figsize=fs, dpi=dpi)` and `axes=fig.subplots(nrows=1, ncols=1)` – Tom Nov 29 '19 at 21:37

0 Answers0