2013-06-28 658 views
14

我有这个可滚动的框架(实际上是在画布内部的框架)。Python tkinter绑定滚轮滚动条

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) 

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

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

这是函数:

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

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

回答

35

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

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

注意self.canvas.bind_all是有点误导 - 你更准确的应该叫root.bind_all,但我不知道是什么或你如何定义你的根窗口。无论如何,这两个电话是同义词。

平台的差异:

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

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

+0

像我这样的初学者的完美答案。谢谢 –

+2

我试图使用这个(linux在这里),但无法使其工作,直到我注意到 - 我想知道为什么 - event.delta总是零。通过简单地调用yview_scroll(direction,“units”)解决它 – alessandro

+0

@Bryan Oakley - 如果应用程序中只有一个滚动画布,上述工作正常。但是,如果有两个或更多,您如何限制滚动到一个或另一个? – JDM

5

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

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

很好,工作示例。只需在Py3上用'tkinter'替换'Tkinter' – Nils

+1

如果这个链接停下来,这个答案就没用了。 [“总是引用重要链接中最相关的部分,以防目标站点无法访问或永久脱机。”](http://stackoverflow.com/help/how-to-answer)请编辑您的问题以避免这个。 – joejoe31b

0

基础上@ BrayanOakley的答案我可以建议细化:

您可以绑定到<Enter><Leave>事件用帆布内的滚动框架发生了两种不同的包装方式如下(scrollwindow是在我的情况下,帧被插入到画布中):

.... 

    self.scrollwindow.bind('<Enter>', self._bound_to_mousewheel) 
    self.scrollwindow.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") 

因此,只有焦点窗口小部件(当前有鼠标光标的窗口)才会滚动。随时请求澄清

1

要摆脱怪异的因素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()