在可滚动框架上使用鼠标滚轮

问题描述

我使用此处提供的可滚动框架类在 tkinter 上工作: https://gist.github.com/mp035/9f2027c3ef9172264532fcd6262f3b01

这个类的实际代码是:

class ScrollFrame(ttk.Frame):
    def __init__(self,parent):
        super().__init__(parent) # create a frame (self)

        s=ttk.Style()
        s.configure('TFrame',background="#eff0f1")

        #place canvas on self
        self.canvas = tk.Canvas(self,borderwidth=0,background="#eff0f1",height = appHeight)
        #place a frame on the canvas,this frame will hold the child widgets
        self.viewPort = ttk.Frame(self.canvas,style='TFrame')
        #place a scrollbar on self
        self.vsb = ttk.Scrollbar(self,orient="vertical",command=self.canvas.yview)
        #attach scrollbar action to scroll of canvas
        self.canvas.configure(yscrollcommand=self.vsb.set)

        #pack scrollbar to right of self
        self.vsb.pack(side="right",fill="y")
        #pack canvas to left of self and expand to fil
        self.canvas.pack(side="left",fill="both",expand=True)
        self.canvas_window = self.canvas.create_window((4,4),#add view port frame to canvas
                                                 window=self.viewPort,anchor="nw",tags="self.viewPort")

        #bind an event whenever the size of the viewPort frame changes.
        self.viewPort.bind("<Configure>",self.onFrameConfigure)
        #bind an event whenever the size of the viewPort frame changes.
        self.canvas.bind("<Configure>",self.onCanvasConfigure)

        #perform an initial stretch on render,otherwise the scroll region has a tiny border until the first resize
        self.onFrameConfigure(None)

    def onFrameConfigure(self,event):
        '''Reset the scroll region to encompass the inner frame'''
        #whenever the size of the frame changes,alter the scroll region respectively.
        self.canvas.configure(scrollregion=self.canvas.bBox("all"))

    def onCanvasConfigure(self,event):
        '''Reset the canvas window to encompass inner frame when required'''
        canvas_width = event.width
        #whenever the size of the canvas changes alter the window region respectively.
        self.canvas.itemconfig(self.canvas_window,width = canvas_width)

它实际上工作得很好,除了我不能让鼠标滚轮在滚动条上工作……我必须点击滑块让它滑动。每当我尝试使用鼠标滚轮滚动时,控制台中都会出现此错误

Traceback (most recent call last):
  File "D:\Anaconda\lib\tkinter\__init__.py",line 1705,in __call__
    return self.func(*args)
  File "D:\Anaconda\lib\tkinter\__init__.py",line 1739,in yview
    res = self.tk.call(self._w,'yview',*args)
_tkinter.TclError: unkNown option "": must be moveto or scroll

我找到了这个话题: tkinter: binding mousewheel to scrollbar

但为适应我的课程而给出的答案似乎都不起作用。

有谁知道我如何调整我的可滚动框架以使鼠标滚轮工作? 提前致谢!!

解决方法

好的,我找到了答案,所以我在这里发布了解决方案:

init 的末尾,我添加了这个:

        self.viewPort.bind('<Enter>',self._bound_to_mousewheel)
        self.viewPort.bind('<Leave>',self._unbound_to_mousewheel)

然后在我添加这个之后:

    def _bound_to_mousewheel(self,event):
        self.canvas.bind_all("<MouseWheel>",self._on_mousewheel)

    def _unbound_to_mousewheel(self,event):
        self.canvas.unbind_all("<MouseWheel>")

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

我现在可以用鼠标滚轮在指针所在的位置滚动条!

这里是完全工作的可滚动框架类代码:

class ScrollFrame(ttk.Frame):
    def __init__(self,parent):
        super().__init__(parent) # create a frame (self)

        s=ttk.Style()
        s.configure('TFrame',background="#eff0f1")

        #place canvas on self
        self.canvas = tk.Canvas(self,borderwidth=0,background="#eff0f1",height = appHeight)
        #place a frame on the canvas,this frame will hold the child widgets
        self.viewPort = ttk.Frame(self.canvas,style='TFrame')
        #place a scrollbar on self
        self.vsb = ttk.Scrollbar(self,orient="vertical")
        #attach scrollbar action to scroll of canvas
        self.canvas.configure(yscrollcommand=self.vsb.set)

        #pack scrollbar to right of self
        self.vsb.pack(side="right",fill="y")
        #pack canvas to left of self and expand to fil
        self.canvas.pack(side="left",fill="both",expand=True)
        self.canvas_window = self.canvas.create_window((4,4),#add view port frame to canvas
                                                 window=self.viewPort,anchor="nw",tags="self.viewPort")

        #bind an event whenever the size of the viewPort frame changes.
        self.viewPort.bind("<Configure>",self.onFrameConfigure)
        #bind an event whenever the size of the viewPort frame changes.
        self.canvas.bind("<Configure>",self.onCanvasConfigure)

        #perform an initial stretch on render,otherwise the scroll region has a tiny border until the first resize
        self.onFrameConfigure(None)

        self.viewPort.bind('<Enter>',self._unbound_to_mousewheel)

    def _bound_to_mousewheel(self,"units")

    def onFrameConfigure(self,event):
        '''Reset the scroll region to encompass the inner frame'''
        #whenever the size of the frame changes,alter the scroll region respectively.
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

    def onCanvasConfigure(self,event):
        '''Reset the canvas window to encompass inner frame when required'''
        canvas_width = event.width
        #whenever the size of the canvas changes alter the window region respectively.
        self.canvas.itemconfig(self.canvas_window,width = canvas_width)

当你想在 tkinter 中创建一个页面时,你所要做的就是这样调用它:

class NewPage(ttk.Frame):
    def __init__(self,parent,controller):

        ttk.Frame.__init__(self,parent)

        self.scrollFrame = ScrollFrame(self)

如果你想在其中添加小部件,只需像这样使用“self.scrollFrame.viewPort”构建它们:

label = ttk.Label(self.scrollFrame.viewPort,text = "Label",anchor = "center")

希望它会帮助某人;)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...