如何通过鼠标滚轮顺利滚动tk画布

时间:2017-03-29 11:14:07

标签: python tkinter

我想滚动画布,所以我使用这段代码绑定到鼠标滚轮:

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

canvas.bind("<MouseWheel>", _on_mousewheel)

但每次我使用鼠标滚轮时,画布都会像向一个位置跳到另一个位置一样滚动。 所以我尝试将yscrollincrement改为10:

canvas.config(yscrollincrement = 10)

它更平滑,但对我来说还不够,如果我将其更改为1,则滚动速度太慢。

我尝试使用循环来执行此操作并使用time.sleep来降低速度,但它不起作用,它将冻结直到循环结束并滚动到结束位置而不进行处理。

如何像Chrome或Firefox一样平滑地滚动画布?

我想要的只是像yscrollincrement = 1那样滚动,但速度很快。

尝试使用后:

def _on_mousewheel(event): 
    canv.config(yscrollincrement = 1) 
    num = 0
    def sc(num, ud):
        canv.yview_scroll(ud, "units") 
        num += 1
        if num < 500:
        #root or canv is the same
            canv.after(1,sc(num, ud))
    ud = int(-1*(event.delta/120))
    sc(num, ud)
    canv.config(yscrollincrement = 0)

2 个答案:

答案 0 :(得分:0)

我想要的只是像yscrollincrement = 1一样滚动,但速度很快。

您可以增加“单位”的值以快速滚动。

canvas.yview_scroll(speed, 'units')

示例:

from tkinter import Tk, Canvas, Frame, Label


def FrameWidth(event, canvas):
   canvas_width = event.width
   canvas.itemconfig("my_tag", width = canvas_width)

def onFrameConfigure(canvas):
   canvas.configure(scrollregion=canvas.bbox("all"))

def retag(tag, *args):
   for widget in args:
      widget.bindtags((tag,) + widget.bindtags())

def _on_mousewheel(event, canvas):
   if event.num == 5:
      speed = 10     # between 8 and 13 gives good speed and smoothness
   else:
      speed = -10    # between 8 and 13 gives good speed and smoothness
   canvas.yview_scroll(speed, 'units')

root = Tk()
root.geometry('300x400+300+100')
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
canvas = Canvas(root, bg='white', yscrollincrement=1)      # 1 makes it more smooth
canvas.grid(row=0, column=0, sticky='nsew')
canvas.rowconfigure(0, weight=1)
canvas.columnconfigure(0, weight=1)
frame = Frame(root, bg='white')
frame.grid(row=0, column=0, sticky='ew')
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
canvas.create_window((0,0), window=frame, anchor='nw', tags="my_tag")
l1 = Label(frame, text='Label 1', bg='black', fg='white', height=3)
l1.grid(row=0, column=0, sticky='ew', pady=2)
l2 = Label(frame, text='Label 2', bg='black', fg='white', height=3)
l2.grid(row=1, column=0, sticky='ew', pady=2)
l3 = Label(frame, text='Label 2', bg='black', fg='white', height=3)
l3.grid(row=2, column=0, sticky='ew', pady=2)
l4 = Label(frame, text='Label 2', bg='black', fg='white', height=3)
l4.grid(row=3, column=0, sticky='ew', pady=2)
retag("special", canvas, frame, l1, l2, l3, l4)

canvas.bind('<Configure>', lambda event: FrameWidth(event, canvas))
root.bind('<Configure>', lambda event: onFrameConfigure(canvas))
canvas.bind_class('special', '<Button-4>', lambda event: _on_mousewheel(event, canvas))      # Button 4 and 5 for mouse scroll on linux. Not sure of windows.
canvas.bind_class('special', '<Button-5>', lambda event: _on_mousewheel(event, canvas))

root.mainloop()

答案 1 :(得分:0)

我想已经很久了,但什么都不晚,我有一个解决方案:

def on_mouse_wheel(event=None):
    def _scroll(e=None):
        nonlocal shift_scroll, scroll, scrolled
        if scrolled == 105:
            return
        if shift_scroll:
            canvas.xview_scroll(scroll, 'units')
        else:
            canvas.yview_scroll(scroll, 'units')
        scrolled += 1
        self.after(5, _scroll)

    scrolled = 0
    shift_scroll = (event.state & 0x1) != 0
    scroll = -1 if event.delta > 0 else 1
    _scroll()

在这里您可以将鼠标滚轮事件绑定到该函数,它会平滑滚动。 如果您想增加或减少时间,您可以在 self.after() 的第 11 行中更改它。 注意:self.after() 中的时间以毫秒为单位。