2013-06-28 719 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()