用于在画布上滚动的 Tkinter 鼠标滚轮动作 [英] Tkinter Mousewheel action for scrolling on canvas

查看:68
本文介绍了用于在画布上滚动的 Tkinter 鼠标滚轮动作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Python 新手,在向画布添加鼠标滚动操作时遇到问题.我有一个垂直滚动条.当我手动滚动滚动条时,滚动条工作正常,或者将鼠标悬停在它上面并滚动鼠标滚轮.我的问题是,我希望能够在我的画布上滚动鼠标滚轮,甚至只是我的框架,只要我的鼠标悬停在它上面,就可以滚动其中的内容.我花了几个小时在stackoverflow上查看与此相关的所有类似问题,但我的修改似乎都不起作用.我目前遇到一个我无法纠正的奇怪错误.由于我的修改,错误仅在我开始滚动时出现,但不会导致崩溃.错误是:-

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. 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:-

            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"类型转换,则会出现此错误:-

Now if I remove the "int" typecast I get this error:-

             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"

所以现在我被困在两个错误之间.

So now I am stuck going back and forth between the two errors.

这是我的代码:-

            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()

推荐答案

除法结果是浮点数.尝试使用整数除法:

When you divide the result is a float. Try with integer division instead:

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

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

Now, you may want to check which widget the mouse pointer is hovering above because the _on_mousewheel() function is invoked when the mouse pointer hovers on the scrollbar, making it scroll twice as fast.

这篇关于用于在画布上滚动的 Tkinter 鼠标滚轮动作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆