title: Tkinter Mousewheel action for scrolling on canvas
body: <p>I am new to Python and I have an issue adding mouse scrolling action to my canvas. I have a vertical scrollbar. The scrollbar works fine when I manually scroll it, or mouse over it and roll my mousewheel. My issue is that I would like to be able roll my mousewheel on my canvas or even just my frame and have the contents inside it scroll as long as my mouse is hovering over it.</p>
  <p>I have spent hours looking at all the similar questions related to this here on stackoverflow, and none of my modifications seem to work. I am currently getting a weird error that I cannot rectify. Due to my modifications, the error ONLY shows up when I start scrolling, however it does not cause a crash. The error is:</p>
  <pre><code>Exception in Tkinter callback
      Traceback (most recent call last):
          File &quot;C:\Users\twaku\Anaconda3\lib\tkinter\__init__.py&quot;, line 1699, in __call__
                  return self.func(*args)
          File &quot;C:/Users/twaku/PycharmProjects/DCSui/FileToSubmit.py&quot;, line 152, in _on_mousewheel
                  self.canvas.yview_scroll(int(-1 * (event.delta / 120), &quot;units&quot;))
          TypeError: 'str' object cannot be interpreted as an integer
  </code></pre>
  <p>Now if I remove the <code>int</code> typecast I get this error:</p>
  <pre><code>Exception in Tkinter callback
      Traceback (most recent call last):
          File &quot;C:\Users\twaku\Anaconda3\lib\tkinter\__init__.py&quot;, line 1699, in __call__
                  return self.func(*args)
          File &quot;C:/Users/twaku/PycharmProjects/DCSui/FileToSubmit.py&quot;, line 156, in _on_mousewheel
                  self.canvas.yview_scroll(-1 * (event.delta / 120), &quot;units&quot;)
          File &quot;C:\Users\twaku\Anaconda3\lib\tkinter\__init__.py&quot;, line 1745, in yview_scroll
                  self.tk.call(self._w, 'yview', 'scroll', number, what)
              _tkinter.TclError: expected integer but got &quot;1.0&quot;
  </code></pre>
  <p>So now I am stuck going back and forth between the two errors.</p>
  <p>Here is my code:</p>
  <pre class="lang-py prettyprint-override"><code>from tkinter import *
  import tkinter as tk
  import time
  import xlrd
  
  
  root = Tk()
  
  
  root.state('zoomed')  # full screen -windowed
  
  # ------------------INTRODUCTION BLOCK--------------
  f1 = Frame(root, width=900, height=700, relief=SUNKEN)
  f1.grid_rowconfigure(1, weight=1)
  f1.grid_columnconfigure(2, weight=1)
  f1.pack(fill=BOTH, expand=1, side=BOTTOM)
  
  root.title(&quot;Diagram Scroll Test&quot;)
  
  Tops = Frame(root, width=1600, height=50, relief=SUNKEN)
  Tops.pack(side=TOP)
  
  # ------------------TIME--------------
  localtime = time.asctime(time.localtime(time.time()))
  # -----------------INFO TOP------------
  lblinfo = Label(Tops, font=('aria', 30, 'bold'), text=&quot;My Diagram Scroll Test&quot;,
                  fg=&quot;steel blue&quot;, bd=10, anchor='w')
  lblinfo.grid(row=0, column=0)
  lblinfo = Label(Tops, font=('aria', 20,), text=localtime, fg=&quot;steel blue&quot;, anchor=W)
  lblinfo.grid(row=1, column=0)
  lblinfo = Label(Tops, font=('aria', 15, 'bold'), text=&quot;Please help&quot;, fg=&quot;steel blue&quot;, bd=10,
                  anchor='w')
  lblinfo.grid(row=2, column=0)
  
  # ------------------CANVAS DEFINITION-------------
  
  class CanvasDemo(Frame):
  
  
      def __init__(self,root):
          Frame.__init__(self,root)
  
  
          self.canvas = tk.Canvas(root, borderwidth=0)
          self.canvas.bind_all(&quot;&lt;MouseWheel&gt;&quot;, self._on_mousewheel)
          self.frame = tk.Frame(self.canvas)
          self.vsb = tk.Scrollbar(root, orient=&quot;vertical&quot;, command=self.canvas.yview)
          self.canvas.configure(yscrollcommand=self.vsb.set)
          root.state('zoomed')
          self.vsb.pack(side=&quot;right&quot;, fill=&quot;y&quot;)
          self.canvas.config(width=root.winfo_screenwidth(), height=root.winfo_screenheight())
          # self.canvas.pack(side=&quot;left&quot;, fill=&quot;both&quot;, expand=&quot;1&quot;)
          self.canvas.pack(fill=&quot;both&quot;, expand=&quot;1&quot;)
          self.canvas.create_window((4, 4), window=self.frame, anchor=&quot;nw&quot;,
                                      tags=&quot;self.frame&quot;)
  
          self.frame.bind(&quot;&lt;Configure&gt;&quot;, self.onFrameConfigure)
  
          self.populate()
  
      # ------------------CODE TO CREATE BLOCK DIAGRAMS-------------
  
      def populate(self):
  
  
          i = 0
          turnCount = 0  # Keeps track of how many boxes is used to trigger a turn
  
          # Create Small starter box
          lineVarx1 = 70
          lineVary1 = 50
          lineVarx2 = 120
          lineVary2 = 50
  
          varx1 = 120
          vary1 = 25
          varx2 = 220
          vary2 = 75
  
          varblk = 1
          varline = 1
  
          self.canvas.create_rectangle(20, 40, 70, 60, fill=&quot;green&quot;, tags=&quot;start&quot;)
  
  
  
          while i &lt; 200:  # Provides 104 blocks
  
              # ------------------IF STATEMENT TO CONTROL WHEN DIAGRAM TURNS-------------
  
              if turnCount == 12:  # At Turn Point, initiating turn sequence
                  lineVarx2 = lineVarx2 - 25
                  self.canvas.create_line(lineVarx1, lineVary1, lineVarx2, lineVary2, arrow=&quot;last&quot;, tags=&quot;to_r1&quot;)
                  # Downward line
                  lineVarx1 = lineVarx2
                  lineVary1 = lineVary2
                  lineVary2 = lineVary2 + 50
                  self.canvas.create_line(lineVarx1, lineVary1, lineVarx2, lineVary2, arrow=&quot;last&quot;, tags=&quot;to_r1&quot;)
  
                  # long line to left
                  lineVarx1 = lineVarx2
                  lineVary1 = lineVary2
                  lineVarx2 = lineVarx2 - 1825
                  self.canvas.create_line(lineVarx1, lineVary1, lineVarx2, lineVary2, arrow=&quot;last&quot;, tags=&quot;to_r1&quot;)
  
                  # Downward line
                  lineVarx1 = lineVarx2
                  lineVary1 = lineVary2
                  lineVary2 = lineVary2 + 50
                  self.canvas.create_line(lineVarx1, lineVary1, lineVarx2, lineVary2, arrow=&quot;last&quot;, tags=&quot;to_r1&quot;)
  
                  lineVary1 = lineVary2
                  lineVarx2 = lineVarx2 + 50
  
                  varx1 = lineVarx2
                  vary1 = lineVary2 - 25
                  varx2 = lineVarx2 + 100
                  vary2 = lineVary2 + 25
                  turnCount = 0
  
              self.canvas.create_line(lineVarx1, lineVary1, lineVarx2, lineVary2, arrow=&quot;last&quot;, tags=&quot;to_r1&quot;)
              self.canvas.create_rectangle(varx1, vary1, varx2, vary2, fill=&quot;bisque&quot;, tags=&quot;r1&quot;)
              self.canvas.create_text(varx1 + 20, vary1, fill=&quot;darkblue&quot;, anchor=NW,
                                      text=&quot;Hi&quot;)
              self.canvas.create_text(varx1 + 20, vary1 + 10, fill=&quot;darkblue&quot;, anchor=NW,
                                      text=&quot;bye&quot;)
              self.canvas.create_text(varx1 + 20, vary1 + 20, fill=&quot;darkblue&quot;, anchor=NW,
                                      text=&quot;fly&quot;)
              lineVarx1 = lineVarx1 + 150
              lineVarx2 = lineVarx2 + 150
              varx1 = varx1 + 150
              varx2 = varx2 + 150
              i += 1
              turnCount += 1
  
          # &quot;End&quot; Block
          lineVarx1 = varx2 - 150
          lineVarx2 = lineVarx1 + 50
  
          varx1 = lineVarx2
          vary1 = lineVary1 - 10
          varx2 = varx1 + 50
          vary2 = lineVary1 + 10
  
          self.canvas.create_line(lineVarx1, lineVary1, lineVarx2, lineVary2, arrow=&quot;last&quot;, tags=&quot;to_r1&quot;)
          self.canvas.create_rectangle(varx1, vary1, varx2, vary2, fill=&quot;red&quot;, tags=&quot;r1&quot;)
  
  
  
  
  
  
      def _on_mousewheel(self, event):
              self.canvas.yview_scroll(-1 * (event.delta / 120), &quot;units&quot;)
  
  
  
      def onFrameConfigure(self, event):
          '''Reset the scroll region to encompass the inner frame'''
          self.canvas.configure(scrollregion=self.canvas.bbox(&quot;all&quot;))
  
  
  
  def qexit():
      root.destroy()
  
  
  btnexit = Button(f1, padx=16, pady=7, bd=10, fg=&quot;black&quot;, font=('ariel', 12, 'bold'), width=8, text=&quot;EXIT&quot;,
                      bg=&quot;powder blue&quot;, command=qexit)
  btnexit.grid(row=15, column=2)
  
  
  
  
  
  canvas = CanvasDemo(root)
  canvas.pack()
  
  mainloop()
  </code></pre>