Python tkinter绑定鼠标滚轮到滚动条

Chr*_*ung 28 python binding tkinter scrollbar mousewheel

我有这个可滚动的框架(实际上是画布内的框架).

import Tkinter as tk
class Scrollbarframe():
    def __init__(self, parent,xsize,ysize,xcod,ycod):
        def ScrollAll(event):
                canvas1.configure(scrollregion=canvas1.bbox("all"),width=xsize,height=ysize,bg='white')
        self.parent=parent
        self.frame1=tk.Frame(parent,bg='white')
        self.frame1.place(x=xcod,y=ycod)
        canvas1=tk.Canvas(self.frame1)
        self.frame2=tk.Frame(canvas1,bg='white',relief='groove',bd=1,width=1230,height=430)
        scrollbar1=tk.Scrollbar(self.frame1,orient="vertical",command=canvas1.yview)
        canvas1.configure(yscrollcommand=scrollbar1.set)
        scrollbar1.pack(side="right",fill="y")
        canvas1.pack(side="left")
        canvas1.create_window((0,0),window=self.frame2,anchor='nw')
        self.frame2.bind("<Configure>",ScrollAll)
Run Code Online (Sandbox Code Playgroud)

我想将鼠标滚轮绑定到滚动条,以便用户可以向下滚动框架,而无需使用滚动条上的箭头按钮.环顾四周后,我添加了一个canvas1像我这样的绑定

self.frame1.bind("<MouseWheel>", self.OnMouseWheel)
Run Code Online (Sandbox Code Playgroud)

这是功能:

def OnMouseWheel(self,event):
    self.scrollbar1.yview("scroll",event.delta,"units")
    return "break" 
Run Code Online (Sandbox Code Playgroud)

但是当我使用鼠标滚轮时,滚动条不会移动.谁能帮我这个?我想要的只是当用户使用鼠标滚轮(在框架区域内/滚动条上)时,画布应自动向上或向下滚动.

Bry*_*ley 50

也许最简单的解决方案是为鼠标滚轮进行全局绑定.然后无论鼠标下的哪个小部件或哪个小部件具有键盘焦点,它都会触发.然后,您可以无条件地滚动画布,或者您可以很聪明并找出哪些窗口应该滚动.

例如,在Windows上你会做这样的事情:

self.canvas = Canvas(...)
self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
...
def _on_mousewheel(self, event):
    self.canvas.yview_scroll(-1*(event.delta/120), "units")
Run Code Online (Sandbox Code Playgroud)

请注意,self.canvas.bind_all这有点误导 - 您应该更正确地调用,root.bind_all但我不知道您定义根窗口的内容或方式.无论如何,这两个电话都是同义词.

平台差异:

  • 在Windows上,你绑定到<MouseWheel>,你需要除以event.delta120(或一些其他因素取决于你想要滚动的速度)
  • 在OSX上,你绑定到<MouseWheel>,你需要使用event.delta而无需修改
  • 在X11系统上你需要绑定到<Button-4><Button-5>,你需要除以event.delta120(或一些其他因素取决于你想要滚动的速度)

有更多精确的解决方案涉及虚拟事件,并确定哪个窗口具有焦点或在鼠标下,或通过绑定传递画布窗口引用,但希望这将使您开始.

  • 根据你的回答,我发现了很多有价值的修改:`self.canvas.bind_all('<MouseWheel>',lambda事件:self.canvas.yview_scroll(int(-1*(event.delta)/120)),"单位"))`.使用Python 3.4,如果数字没有被转换为`int`,则解释器抛出`_tkinter.TclError:期望的整数但得到"1.0". (6认同)
  • 我试图使用这个(linux这里),但无法使它工作,直到我注意到 - 我想知道为什么 - event.delta总是为零.通过简单地调用yview_scroll(方向,"单位")来解决它 (4认同)
  • @JDM:您可以使用 `winfo_ contains` 来确定光标下的画布,然后滚动该画布。 (3认同)
  • @Bryan Oakley - 如果应用程序中只有一个滚动画布,则上述方法可以正常工作。但是如果有两个或更多,你怎么能限制滚动到一个或另一个? (2认同)
  • @BryanOakley:好的,我想我明白了。我从不同的方向进行处理,使用小部件的 &lt;Enter&gt; 和 &lt;Leave&gt; 事件来触发 .bind_all 和 .unbind 调用。真正的麻烦是弄清楚为什么 Tkinter 接受 .bind_all 的回调,但抱怨它需要一个字符串来代替 .unbind。(我已经排除了全局 unbind 或 unbind_all,因为我不想弄乱可能存在的其他绑定。)无论如何,经过大量搜索,我终于找到了一篇显示正确字符串语法的文章:https://mail .python.org/pipermail//tkinter-discuss/2012-May/003152.html (2认同)

Mik*_* T. 19

基于@ BryanOakley的回答,这里是一种仅滚动聚焦小部件的方法(即当前鼠标光标所在的小部件).

绑定到<Enter><Leave>事件的发生,其位于画布内的滚动框上,通过以下方式(scrollframe是画布内框):

    ....

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

    return

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

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

def _on_mousewheel(self, event):
    self.canv.yview_scroll(int(-1*(event.delta/120)), "units")
Run Code Online (Sandbox Code Playgroud)

  • 这应该是选择的答案,因为它提供了大多数应用程序都需要的有针对性的方法。 (4认同)

Joe*_*ail 8

此链接为您提供了如何使用滚轮的示例.

http://www.daniweb.com/software-development/python/code/217059/using-the-mouse-wheel-with-tkinter-python

我希望这有帮助!

# explore the mouse wheel with the Tkinter GUI toolkit
# Windows and Linux generate different events
# tested with Python25
import Tkinter as tk
def mouse_wheel(event):
    global count
    # respond to Linux or Windows wheel event
    if event.num == 5 or event.delta == -120:
        count -= 1
    if event.num == 4 or event.delta == 120:
        count += 1
    label['text'] = count
count = 0
root = tk.Tk()
root.title('turn mouse wheel')
root['bg'] = 'darkgreen'
# with Windows OS
root.bind("<MouseWheel>", mouse_wheel)
# with Linux OS
root.bind("<Button-4>", mouse_wheel)
root.bind("<Button-5>", mouse_wheel)
label = tk.Label(root, font=('courier', 18, 'bold'), width=10)
label.pack(padx=40, pady=40)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)

  • 如果此链接出现故障,这个答案将毫无用处.["始终引用重要链接中最相关的部分,以防目标网站无法访问或永久脱机."(http://stackoverflow.com/help/how-to-answer)请编辑您的问题以避免这个. (2认同)

小智 8

为了摆脱奇怪的因素120,我们可以看一下event.delta值的符号.这使得在Windows,Linux和Mac OS下使用相同的处理程序变得容易.

# Mouse wheel handler for Mac, Windows and Linux
# Windows, Mac: Binding to <MouseWheel> is being used
# Linux: Binding to <Button-4> and <Button-5> is being used

def MouseWheelHandler(event):
    global count

    def delta(event):
        if event.num == 5 or event.delta < 0:
            return -1 
        return 1 

    count += delta(event)
    print(count)

import tkinter
root = tkinter.Tk()
count = 0
root.bind("<MouseWheel>",MouseWheelHandler)
root.bind("<Button-4>",MouseWheelHandler)
root.bind("<Button-5>",MouseWheelHandler)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)