title: python tkinter canvas not resizing
body: <p>I'm trying to subclass some tkinter controls to make an auto scrolling frame for use in my program, i only want it to scroll vertically, and when widgets are added that need it to scroll horizontally instead to resize the parent to fit. widgets that go in this frame are not all defined at runtime and are created dynamically, so it must react to events. I have some code that is partly working, in that it i run it, i can use the buttons at the bottom to add and remove labels on the fly, if i do this without manually resizing the window first then it works as expected. however if i manually resize the window the horizontal resizing stops working:</p>
  
  <pre><code>from tkinter import *
  
  __all__ = ["VerticalScrolledFrame"]
  
  class VerticalScrolledFrame(Frame):
      def __init__(self, parent, *args, **kw):
          Frame.__init__(self, parent, *args, **kw)            
          self.grid_columnconfigure(1, weight=1)
          self.grid_rowconfigure(1, weight=1)
          # create a canvas object and a vertical scrollbar for scrolling it
          self.vscrollbar = Scrollbar(self, orient=VERTICAL)
          self.vscrollbar.grid(column=2, row=1, sticky="nesw")
          self.canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=self.vscrollbar.set, height=10, width=10)
          self.canvas.grid(column=1, row=1, sticky="nesw")
          self.vscrollbar.config(command=self.canvas.yview)
  
          # reset the view
          self.canvas.xview_moveto(0)
          self.canvas.yview_moveto(0)
  
          # create a frame inside the canvas which will be scrolled with it
          self.interior = Frame(self.canvas)
          self.interior_id = self.canvas.create_window(0, 0, window=self.interior, anchor=NW)
  
          self.interior.bind('&lt;Configure&gt;', self._configure_interior)
  
          # track changes to the canvas and frame width and sync them,
          # also updating the scrollbar
      def _configure_interior(self, event=None):
          print("config interior")
          # update the scrollbars to match the size of the inner frame
          size = (self.interior.winfo_width(), self.interior.winfo_height())
          self.canvas.config(scrollregion="0 0 %s %s" % size)
          if self.interior.winfo_reqwidth() &gt; self.canvas.winfo_width():
              # update the canvas's width to fit the inner frame
              self.canvas.config(width=self.interior.winfo_reqwidth())
  
  if __name__ == "__main__":
      labels = []
      labels2 = []
      def add1():
          l = Label(f.interior, text=str(len(labels)+1))
          l.grid(column=len(labels)+1, row=1)
          labels.append(l)
  
      def remove1():
          l = labels.pop()
          l.grid_forget()
          l.destroy()
  
      def add2():
          l = Label(f.interior, text=str(len(labels2)+1))
          l.grid(column=1, row=len(labels2)+1)
          labels2.append(l)
  
      def remove2():
          l = labels2.pop()
          l.grid_forget()
          l.destroy()
  
      app = Tk()
      app.grid_columnconfigure(1, weight=1)
      app.grid_columnconfigure(2, weight=1)
      app.grid_rowconfigure(1, weight=1)
      f = VerticalScrolledFrame(app)
      f.grid(column=1, row=1, columnspan=2, sticky="nesw")
      Button(app, text="Add-H", command=add1).grid(column=1, row=2, sticky="nesw")
      Button(app, text="Remove-H", command=remove1).grid(column=2, row=2, sticky="nesw")
      Button(app, text="Add-V", command=add2).grid(column=1, row=3, sticky="nesw")
      Button(app, text="Remove-V", command=remove2).grid(column=2, row=3, sticky="nesw")
      app.mainloop()
  </code></pre>
  
  <p>I'm working solely on windows and using python 3.3, I tried 3.4 as well but no change.</p>
  
  <p>why does resizing the window stop the call to:</p>
  
  <pre><code>self.canvas.config(width=self.interior.winfo_reqwidth())
  </code></pre>
  
  <p>from working?</p>
  
  <p>EDIT:
  Brian Oakley's response makes sense so I can understand that behavior, however i have now changed my code to also handle changes to the canvas size when the window is resized:</p>
  
  <pre><code>from tkinter import *
  
  __all__ = ["VerticalScrolledFrame"]
  
  class VerticalScrolledFrame(Frame):
      def __init__(self, parent, *args, **kw):
          Frame.__init__(self, parent, *args, **kw)
          p = parent
          while True:
              if p.winfo_class() in ['Tk', 'Toplevel']:
                  break
              else:
                  p = self._nametowidget(p.winfo_parent())
          self.root_window = p
          self.grid_columnconfigure(1, weight=1)
          self.grid_rowconfigure(1, weight=1)
          # create a canvas object and a vertical scrollbar for scrolling it
          self.vscrollbar = Scrollbar(self, orient=VERTICAL)
          self.vscrollbar.grid(column=2, row=1, sticky="nesw")
          self.canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=self.vscrollbar.set, height=10, width=10)
          self.canvas.grid(column=1, row=1, sticky="nesw")
          self.vscrollbar.config(command=self.canvas.yview)
  
          # reset the view
          self.canvas.xview_moveto(0)
          self.canvas.yview_moveto(0)
  
          # create a frame inside the canvas which will be scrolled with it
          self.interior = Frame(self.canvas)
          self.interior_id = self.canvas.create_window(0, 0, window=self.interior, anchor=NW)
  
          self.interior.bind('&lt;Configure&gt;', self._configure_interior)
  
          self.canvas.bind('&lt;Configure&gt;', self._configure_canvas)
  
          # track changes to the canvas and frame width and sync them,
          # also updating the scrollbar
      def _configure_interior(self, event=None):
          print("config interior")
          # update the scrollbars to match the size of the inner frame
          size = (self.interior.winfo_width(), self.interior.winfo_height())
          self.canvas.config(scrollregion="0 0 %s %s" % size)
          if self.interior.winfo_reqwidth() &gt;= self.canvas.winfo_width():
              # update the canvas's width to fit the inner frame
              # only works before mainloop
              self.canvas.config(width=self.interior.winfo_reqwidth())
          screen_h = self.winfo_screenheight()
          if ((self.root_window.winfo_rooty() + self.root_window.winfo_height() - self.canvas.winfo_height() + self.interior.winfo_reqheight()) &lt; screen_h):
              self.canvas.configure(height=self.interior.winfo_reqheight())
  
      def _configure_canvas(self, event=None):
          print("config canvas")
          if self.interior.winfo_reqwidth() &lt; self.canvas.winfo_width():
              self.canvas.itemconfigure(self.interior_id, width=self.canvas.winfo_width())
          elif self.interior.winfo_reqwidth() &gt; self.canvas.winfo_width():
              self.canvas.config(width=self.interior.winfo_reqwidth())
  
          if (self.interior.winfo_reqheight() &lt; self.canvas.winfo_height()) or (self.interior.winfo_height() &lt; self.canvas.winfo_height()):
              self.canvas.itemconfigure(self.interior_id, height=self.canvas.winfo_height())
  
  if __name__ == "__main__":
      labels = []
      labels2 = []
      def add1():
  ##        app.geometry("")
          l = Label(f.interior, text=str(len(labels)+1))
          l.grid(column=len(labels)+1, row=1)
          f.interior.grid_columnconfigure(len(labels)+1, weight=1, minsize=l.winfo_reqwidth())
          labels.append(l)
  
      def remove1():
  ##        app.geometry("")
          l = labels.pop()
          l.grid_forget()
          f.interior.grid_columnconfigure(len(labels)+2, weight=0, minsize=0)
          l.destroy()
  
      def add2():
          l = Label(f.interior, text=str(len(labels2)+1))
          l.grid(column=1, row=len(labels2)+1)
          f.interior.grid_rowconfigure(len(labels2)+1, weight=1, minsize=l.winfo_reqheight())
          labels2.append(l)
  
      def remove2():
          l = labels2.pop()
          l.grid_forget()
          f.interior.grid_rowconfigure(len(labels2)+2, weight=0, minsize=0)
          l.destroy()
  
      app = Tk()
      app.grid_columnconfigure(1, weight=1)
      app.grid_columnconfigure(2, weight=1)
      app.grid_rowconfigure(1, weight=1)
      f = VerticalScrolledFrame(app)
      f.grid(column=1, row=1, columnspan=2, sticky="nesw")
      Button(app, text="Add-H", command=add1).grid(column=1, row=2, sticky="nesw")
      Button(app, text="Remove-H", command=remove1).grid(column=2, row=2, sticky="nesw")
      Button(app, text="Add-V", command=add2).grid(column=1, row=3, sticky="nesw")
      Button(app, text="Remove-V", command=remove2).grid(column=2, row=3, sticky="nesw")
      for i in range(0,10):
          add1()
          add2()
      app.mainloop()
  </code></pre>
  
  <p>the problem I am now seeing is that if I add items vertically before resizing the window, the <code>_configure_interior</code> function is called for each widget that gets added and the window is either resized vertically to fit (if before window sizing) and it is supposed to update the scrollregion (and scrollbar) if not, however after resizing the window the <code>_configure_interior</code> stops being called as each widget is added, and if i call it manually the scrollbar is still not updated?</p>