python - 用于在 Canvas 上滚动的 Tkinter 鼠标滚轮操作

标签 python tkinter scroll mousewheel

我是 Python 新手,在向 Canvas 添加鼠标滚动操作时遇到问题。我有一个垂直滚动条。当我手动滚动滚动条或将鼠标悬停在滚动条上并滚动鼠标滚轮时,滚动条工作正常。我的问题是,我希望能够在 Canvas 上滚动鼠标滚轮,甚至只是在框架上滚动,只要鼠标悬停在其上,其中的内容就会滚动。

我花了几个小时在 stackoverflow 上查看与此相关的所有类似问题,但我的修改似乎都不起作用。我目前遇到一个无法纠正的奇怪错误。由于我的修改,错误仅在我开始滚动时显示,但不会导致崩溃。错误是:

Exception in Tkinter callback
    Traceback (most recent call last):
        File "C:\Users\twaku\Anaconda3\lib\tkinter\__init__.py", line 1699, in __call__
                return self.func(*args)
        File "C:/Users/twaku/PycharmProjects/DCSui/FileToSubmit.py", line 152, in _on_mousewheel
                self.canvas.yview_scroll(int(-1 * (event.delta / 120), "units"))
        TypeError: 'str' object cannot be interpreted as an integer

现在,如果我删除 int 类型转换,则会收到此错误:

Exception in Tkinter callback
    Traceback (most recent call last):
        File "C:\Users\twaku\Anaconda3\lib\tkinter\__init__.py", line 1699, in __call__
                return self.func(*args)
        File "C:/Users/twaku/PycharmProjects/DCSui/FileToSubmit.py", line 156, in _on_mousewheel
                self.canvas.yview_scroll(-1 * (event.delta / 120), "units")
        File "C:\Users\twaku\Anaconda3\lib\tkinter\__init__.py", line 1745, in yview_scroll
                self.tk.call(self._w, 'yview', 'scroll', number, what)
            _tkinter.TclError: expected integer but got "1.0"

所以现在我在这两个错误之间来回徘徊。

这是我的代码:

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("Diagram Scroll Test")

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="My Diagram Scroll Test",
                fg="steel blue", bd=10, anchor='w')
lblinfo.grid(row=0, column=0)
lblinfo = Label(Tops, font=('aria', 20,), text=localtime, fg="steel blue", anchor=W)
lblinfo.grid(row=1, column=0)
lblinfo = Label(Tops, font=('aria', 15, 'bold'), text="Please help", fg="steel blue", 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("<MouseWheel>", self._on_mousewheel)
        self.frame = tk.Frame(self.canvas)
        self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.vsb.set)
        root.state('zoomed')
        self.vsb.pack(side="right", fill="y")
        self.canvas.config(width=root.winfo_screenwidth(), height=root.winfo_screenheight())
        # self.canvas.pack(side="left", fill="both", expand="1")
        self.canvas.pack(fill="both", expand="1")
        self.canvas.create_window((4, 4), window=self.frame, anchor="nw",
                                    tags="self.frame")

        self.frame.bind("<Configure>", 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="green", tags="start")



        while i < 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="last", tags="to_r1")
                # Downward line
                lineVarx1 = lineVarx2
                lineVary1 = lineVary2
                lineVary2 = lineVary2 + 50
                self.canvas.create_line(lineVarx1, lineVary1, lineVarx2, lineVary2, arrow="last", tags="to_r1")

                # long line to left
                lineVarx1 = lineVarx2
                lineVary1 = lineVary2
                lineVarx2 = lineVarx2 - 1825
                self.canvas.create_line(lineVarx1, lineVary1, lineVarx2, lineVary2, arrow="last", tags="to_r1")

                # Downward line
                lineVarx1 = lineVarx2
                lineVary1 = lineVary2
                lineVary2 = lineVary2 + 50
                self.canvas.create_line(lineVarx1, lineVary1, lineVarx2, lineVary2, arrow="last", tags="to_r1")

                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="last", tags="to_r1")
            self.canvas.create_rectangle(varx1, vary1, varx2, vary2, fill="bisque", tags="r1")
            self.canvas.create_text(varx1 + 20, vary1, fill="darkblue", anchor=NW,
                                    text="Hi")
            self.canvas.create_text(varx1 + 20, vary1 + 10, fill="darkblue", anchor=NW,
                                    text="bye")
            self.canvas.create_text(varx1 + 20, vary1 + 20, fill="darkblue", anchor=NW,
                                    text="fly")
            lineVarx1 = lineVarx1 + 150
            lineVarx2 = lineVarx2 + 150
            varx1 = varx1 + 150
            varx2 = varx2 + 150
            i += 1
            turnCount += 1

        # "End" 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="last", tags="to_r1")
        self.canvas.create_rectangle(varx1, vary1, varx2, vary2, fill="red", tags="r1")






    def _on_mousewheel(self, event):
            self.canvas.yview_scroll(-1 * (event.delta / 120), "units")



    def onFrameConfigure(self, event):
        '''Reset the scroll region to encompass the inner frame'''
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))



def qexit():
    root.destroy()


btnexit = Button(f1, padx=16, pady=7, bd=10, fg="black", font=('ariel', 12, 'bold'), width=8, text="EXIT",
                    bg="powder blue", command=qexit)
btnexit.grid(row=15, column=2)





canvas = CanvasDemo(root)
canvas.pack()

mainloop()

最佳答案

除法的结果是 float 。尝试使用整数除法:

def _on_mousewheel(self, event):
    self.canvas.yview_scroll(-1 * (event.delta // 120), "units")
                                        here:--^

现在,您可能想要检查鼠标指针悬停在哪个小部件上方,因为当鼠标指针悬停在滚动条上时会调用 _on_mousewheel() 函数,使其滚动速度提高两倍。

关于python - 用于在 Canvas 上滚动的 Tkinter 鼠标滚轮操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51568717/

相关文章:

javascript - 使用触摸事件滚动页面

python - 用于公开图像的 Django REST API

python - 使用python测量网站的深度

python flask : accessing one particular dictionary item in the template

python - 无法在 Ubuntu 16.04 上使用 pip 安装 uwsgi

python - 在 tkinter(Python) 中获取在 Canvas 中绘制的项目的填充颜色或任何其他属性

jquery - 滚动回网页顶部时触发功能的问题

python - 如何定义脚本从哪里加载文件?

python - 检查是否在 python 中按下了按钮?

android - 在 Horizo​​ntalScrollView 中检测 throw 结束?