Slowing down Tkinter Canvas scrolling in Python
Basically I have the following code working, but i can not find a way to slow down my canvas view dragging, as of now it's going too fast to be functional for my App. This is just a small example that shows what i'm trying to troubleshoot:
from Tkinter import *
import Image, ImageTk
class GUI:
def __init__(self,root):
frame = Frame(root, bd=2, relief=SUNKEN)
frame.grid_ro开发者_StackOverflow社区wconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
xscrollbar = Scrollbar(frame, orient=HORIZONTAL)
xscrollbar.grid(row=1, column=0, sticky=E+W)
yscrollbar = Scrollbar(frame)
yscrollbar.grid(row=0, column=1, sticky=N+S)
self.canvas = Canvas(frame, bd=0, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set)
self.canvas.grid(row=0, column=0, sticky=N+S+E+W)
File = "JPG FILENAME HERE"
self.img = ImageTk.PhotoImage(Image.open(File))
self.canvas.create_image(0,0,image=self.img, anchor="nw")
self.canvas.config(scrollregion=self.canvas.bbox(ALL))
xscrollbar.config(command=self.canvas.xview)
yscrollbar.config(command=self.canvas.yview)
frame.pack()
self.canvas.bind("<Button 3>",self.grab)
self.canvas.bind("<B3-Motion>",self.drag)
def grab(self,event):
self._y = event.y
self._x = event.x
def drag(self,event):
if (self._y-event.y < 0): self.canvas.yview("scroll",-1,"units")
elif (self._y-event.y > 0): self.canvas.yview("scroll",1,"units")
if (self._x-event.x < 0): self.canvas.xview("scroll",-1,"units")
elif (self._x-event.x > 0): self.canvas.xview("scroll",1,"units")
self._x = event.x
self._y = event.y
root = Tk()
GUI(root)
root.mainloop()
ANSWER:
Bryan Oakley's answer did the trick I just changed:
self.canvas = Canvas(frame, bd=0, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set)
to:
self.canvas = Canvas(frame, bd=0, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set,xscrollincrement=10,yscrollincrement=10)
and it worked like a charm.
Try setting the value of the xscrollincrement
and yscrollincrement
attributes of the canvas to something greater than zero. These settings correspond to the units
used when you do call xview
and yview
with a "units" argument (eg: self.canvas.xview("scroll",-1,"units")
.
According to the official Tk documentation, if these values are zero (the default), xview and yview adjusts "...in units of the [x,y]ScrollIncrement option, if it is greater than zero, or in units of one-tenth the window's [width, height] otherwise"
I don't really know what I'm doing here, but this moves more controllably, at least. First, explicitly set the canvas size:
self.canvas = Canvas(frame, bd=0, height=600, width=800,
xscrollcommand=self.xscrollbar.set,
yscrollcommand=self.yscrollbar.set)
Then, in __init__()
, add a couple of instance variables to keep track of the current position:
self.pos_x = self.pos_y = 0.0
Then, replace the drag
method with this:
def drag(self, event):
# Note canvas dimensions are used here
self.pos_x += float(self._x-event.x) / 800.0
self.pos_y += float(self._y-event.y) / 600.0
if self.pos_x < 0.0: self.pos_x = 0.0
elif self.pos_x > 1.0: self.pos_x = 1.0
if self.pos_y < 0.0: self.pos_y = 0.0
elif self.pos_y > 1.0: self.pos_y = 1.0
self.canvas.xview("moveto", self.pos_x)
self.canvas.yview("moveto", self.pos_y)
self._x = event.x
self._y = event.y
I don't know why you have to cast those numbers to float, but it doesn't work if you don't. It's brittle; if you multiply the mouse movement by anything, even just 0.99 or 1.01, the movement gets really wonky; I suspect there's some kind of feedback going on between the mouse movement and the canvas movement. It doesn't play nicely with the scroll bars, either; I suppose we'd have to update pos_x and pos_y when they're moved. As I said, don't really know what I'm doing; I haven't done much GUI programming. Anyway, hope this helps.
Try this, change drag to just use the calculated value:
self.canvas.yview("scroll",self._y-event.y,"units")
self.canvas.xview("scroll",self._x-event.x,"units")
And change your scroll increments to 1.
Now your image should click & drag in sync with the mouse cursor, similar to popular map and document viewers.
精彩评论