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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17355902/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 07:59:42  来源:igfitidea点击:

Python tkinter binding mousewheel to scrollbar

pythonbindingtkinterscrollbarmousewheel

提问by Chris Aung

I have this scroll-able frame (frame inside canvas actually).

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

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)

I would like to bind mouse wheel to the scrollbar so that user can scroll down the frame without having to use arrow buttons on the scrollbar. After looking around, i added a binding to my canvas1like this

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

self.frame1.bind("<MouseWheel>", self.OnMouseWheel)

This is the function:

这是函数:

def OnMouseWheel(self,event):
    self.scrollbar1.yview("scroll",event.delta,"units")
    return "break" 

But the scroll bar won't move when i use mousewheel. Can anyone help me with this? All i want is when the user use mousewheel (inside the frame area/on the scrollbar), the canvas should automatically scroll up or down.

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

采纳答案by Bryan Oakley

Perhaps the simplest solution is to make a global binding for the mousewheel. It will then fire no matter what widget is under the mouse or which widget has the keyboard focus. You can then unconditionally scroll the canvas, or you can be smart and figure out which of your windows should scroll.

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

For example, on windows you would do something like this:

例如,在 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")

Note that self.canvas.bind_allis a bit misleading -- you more correctly should call root.bind_allbut I don't know what or how you define your root window. Regardless, the two calls are synonymous.

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

Platform differences:

平台差异:

  • On Windows, you bind to <MouseWheel>and you need to divide event.deltaby 120 (or some other factor depending on how fast you want the scroll)
  • on OSX, you bind to <MouseWheel>and you need to use event.deltawithout modification
  • on X11 systems you need to bind to <Button-4>and <Button-5>, and you need to divide event.deltaby 120 (or some other factor depending on how fast you want to scroll)
  • 在 Windows 上,您绑定到<MouseWheel>并且需要除以event.delta120(或其他一些因素,具体取决于您希望滚动的速度)
  • 在 OSX 上,你绑定到<MouseWheel>并且你需要event.delta不加修改地使用
  • 在 X11 系统上,您需要绑定到<Button-4><Button-5>,并且需要除以event.delta120(或其他一些因素,具体取决于您要滚动的速度)

There are more refined solutions involving virtual events and determining which window has the focus or is under the mouse, or passing the canvas window reference through the binding, but hopefully this will get you started.

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

回答by Joe Michail

This link gives you an example as to how to use the scrollwheel.

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

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

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

I hope this helps!

我希望这有帮助!

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

回答by Mikhail T.

Based on @BryanOakley's answer, here is a way to scroll only the focused widget (i.e. the one you have mouse cursor currently over).

根据@BryanOakley 的回答,这是一种仅滚动焦点小部件(即当前鼠标光标所在的小部件)的方法。

Bind to <Enter>and <Leave>events happening on your scrollable frame which sits inside a canvas, the following way (scrollframeis the frame that is inside the canvas):

绑定到<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")

回答by Marvo

To get rid of the weird factor 120 we could just look at the sign of the event.delta value. This makes it easy to use the same handler under Windows, Linux and Mac OS.

为了摆脱奇怪的因素 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()

回答by Giovanni G. PY

In case you are interested

如果你有兴趣

How to scroll 2 listbox at the same time

如何同时滚动2个列表框

#listbox scrollbar

from tkinter import *
root = Tk()

def scrolllistbox2(event):
    listbox2.yview_scroll(int(-1*(event.delta/120)), "units")


scrollbar = Scrollbar(root)
#scrollbar.pack(side=RIGHT, fill=Y)
listbox = Listbox(root)
listbox.pack()
for i in range(100):
    listbox.insert(END, i)
# attach listbox to scrollbar
listbox.config(yscrollcommand=scrollbar.set)
listbox.bind("<MouseWheel>", scrolllistbox2)

listbox2 = Listbox(root)
listbox2.pack()
for i in range(100):
    listbox2.insert(END, i+100)
listbox2.config(yscrollcommand=scrollbar.set)

#scrollbar.config(command=listbox.yview)

root.mainloop()