为什么 Python Tkinter Canvas 不滚动?

Why won't the Python Tkinter Canvas Scroll?

为什么我无法让 python tkinter canvas 响应 Apple Magic Mouse 的垂直和水平 swiping/scrolling? canvas 的滚动条正常工作(这意味着水平条在我 swipe/scroll 水平放置在鼠标上时有效,但当我 swipe/scroll 垂直放置时不工作,而垂直滚动条在我 swipe/scroll 垂直但不对任何水平 swiping/scrolling 运动做出反应),但是 canvas 对鼠标的任何 swiping/scrolling 没有反应。

这是我的 example/test 代码:

from tkinter import *
import tkinter.ttk as ttk
from PIL import Image, ImageTk
root = Tk()

h = Scrollbar(root, orient=HORIZONTAL)
v = Scrollbar(root, orient=VERTICAL)
canvas = Canvas(root, scrollregion=(0, 0, 1000, 1000), yscrollcommand=v.set, xscrollcommand=h.set)
h['command'] = canvas.xview
v['command'] = canvas.yview
theImage = ImageTk.PhotoImage(Image.open('example.png')) #Assume a very large image
canvas.create_image(0,0,image=theImage, anchor='nw')
canvas.grid(column=0, row=0, sticky=(N,W,E,S))
h.grid(column=0, row=1, sticky=(W,E))
v.grid(column=1, row=0, sticky=(N,S))
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
root.mainloop()

当涉及到 Python 和 tkinter 时,我完全是个新手,但我觉得这应该非常简单明了(或者至少是可行的)。然而我找遍了仍然找不到答案(尽管我可能使用了错误的术语进行搜索)。

怎样才能让 canvas 像滚动条那样对 Magic Mouse 的 scrolling/swiping 输入作出反应?

编辑:我正在使用 Python 3.4、Tkinter 8.5.18、Mac OS X 10.9.5 和 Apple Magic Mouse

假设魔术鼠标的滚动和滑动输入像标准触控板上的滚动区域一样工作,您需要绑定 <MouseWheel><Shift-MouseWheel> 事件。

首先是代码,然后是一些注释。

from tkinter import *
import tkinter.ttk as ttk
from PIL import Image, ImageTk

def on_vertical(event):
    canvas.yview_scroll(-1 * event.delta, 'units')

def on_horizontal(event):
    canvas.xview_scroll(-1 * event.delta, 'units')

root = Tk()
h = Scrollbar(root, orient=HORIZONTAL)
v = Scrollbar(root, orient=VERTICAL)
canvas = Canvas(root, scrollregion=(0, 0, 1000, 1000), yscrollcommand=v.set, xscrollcommand=h.set)
h['command'] = canvas.xview
v['command'] = canvas.yview
theImage = ImageTk.PhotoImage(Image.open('img'))
canvas.create_image(0,0,image=theImage, anchor='nw')
canvas.grid(column=0, row=0, sticky=(N,W,E,S))

canvas.bind_all('<MouseWheel>', on_vertical)
canvas.bind_all('<Shift-MouseWheel>', on_horizontal)

h.grid(column=0, row=1, sticky=(W,E))
v.grid(column=1, row=0, sticky=(N,S))
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
root.mainloop()

如您所见,只有 2 处更改。

  1. 有两个回调函数来处理滚动事件on_verticalon_horizontal
  2. canvas <MouseWheel><Shift-MouseWheel> 事件分别绑定到 on_verticalon_horizontal

使用ntk Canvas创建一个可滚动的Canvas,默认情况下它适用于鼠标滚动,但如果您创建一个ntk Scrollbar widget,并将其分配给canvas,你很高兴。

ntk 在 tkinter 之上工作,使用 pip 从 pypi 安装它

pip install ntk

使用 ntk widgets 获得很棒的设计。

from ntk import Tk, Canvas, Scrollbar

def main():
    root = Tk()

canvas = Canvas(root)

    root.mainloop()    

if __name__=='__main__':
    main()

这个 canvas 可以通过鼠标滚动滚动,但是如果你想用它设置一个条,你可以创建一个滚动条小部件并将这个 canvas 对象作为第二个参数传递

scroll = Scrollbar(root, canvas)

您可以通过配置更改 canvas 的可滚动区域,或者在 canvas 创建时传递它

canvas = Canvas(root, scrollregion=[0,0,100,50]) # [x1, y1, x2, y2]

或通过

配置
canvas.config(scrollregion=[0,0,100,50])

欢迎使用更少的代码进行漂亮的设计,祝编码愉快。