问题
Why can't I get the python tkinter canvas to respond to the vertical and horizontal swiping/scrolling of Apple's Magic Mouse? The scrollbars for the canvas work properly (meaning the horizontal bar works when I swipe/scroll horizontally on the mouse but not when I swipe/scroll vertically, and the vertical scrollbar moves when I swipe/scroll vertically but doesn't react to any horizontal swiping/scrolling motion), but the canvas doesn't react to any swiping/scrolling of the mouse.
Here is my example/test code:
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()
I'm a total novice when it comes to both Python and tkinter, but I feel like this should be really simple and obvious (or at least do-able). And yet I've looked all over and still can't find the answer (though I might be searching using the wrong jargon).
What does it take to make the canvas react to scrolling/swiping inputs from the Magic Mouse like the scrollbars do already?
Edit: I'm using Python 3.4, Tkinter 8.5.18, Mac OS X 10.9.5, and an Apple Magic Mouse
回答1:
Assuming that the magic mouse's scroll and swipe inputs work like the scrolling regions on a standard trackpad, you need to bind the <MouseWheel>
and <Shift-MouseWheel>
events.
First the code, then some notes.
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()
As you can see there are only 2 changes.
- There are two callback functions to handle the scroll events
on_vertical
andon_horizontal
- The canvas
<MouseWheel>
and<Shift-MouseWheel>
events are bound toon_vertical
andon_horizontal
respectively.
回答2:
Use ntk Canvas to create a scroll able Canvas, by default it works on mouse scroll, but if you create a ntk Scrollbar widget, and assign it to canvas, you are good to go.
ntk works on top of tkinter, to install it from pypi with pip
pip install ntk
use ntk widgets to get awesome design.
from ntk import Tk, Canvas, Scrollbar
def main():
root = Tk()
canvas = Canvas(root)
root.mainloop()
if __name__=='__main__':
main()
this canvas is scroll able by mouse scroll, but if you want to set a bar with it, you can create a scroll bar widget and pass this canvas object as second param
scroll = Scrollbar(root, canvas)
you can change scroll able area from canvas by configure or pass it when canvas is creating
canvas = Canvas(root, scrollregion=[0,0,100,50]) # [x1, y1, x2, y2]
or configure it by
canvas.config(scrollregion=[0,0,100,50])
welcome to beautiful design in less code, happy codding.
来源:https://stackoverflow.com/questions/33400918/why-wont-the-python-tkinter-canvas-scroll