在Python中减慢Tkinter画布滚动速度
基本上,我有以下代码可以正常工作,但我找不到方法来减慢我的画布视图拖动的速度,现在拖动得太快,无法在我的应用中正常使用。这只是一个小例子,展示了我正在尝试解决的问题:
from Tkinter import *
import Image, ImageTk
class GUI:
def __init__(self,root):
frame = Frame(root, bd=2, relief=SUNKEN)
frame.grid_rowconfigure(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()
回答:
Bryan Oakley 的回答解决了我的问题,我只是把:
self.canvas = Canvas(frame, bd=0, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set)
改成:
self.canvas = Canvas(frame, bd=0, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set,xscrollincrement=10,yscrollincrement=10)
然后它就完美运行了。
3 个回答
0
试试这个,把拖动的部分改成只使用计算出来的值:
self.canvas.yview("scroll",self._y-event.y,"units")
self.canvas.xview("scroll",self._x-event.x,"units")
然后把你的滚动增量改成1。
现在你的图片应该可以跟着鼠标光标一起点击和拖动,就像常见的地图和文档查看器那样。
2
我其实不太清楚自己在做什么,不过这样移动起来更可控一些。首先,明确设置画布的大小:
self.canvas = Canvas(frame, bd=0, height=600, width=800,
xscrollcommand=self.xscrollbar.set,
yscrollcommand=self.yscrollbar.set)
然后,在 __init__()
里,添加几个实例变量来记录当前的位置:
self.pos_x = self.pos_y = 0.0
接着,把 drag
方法替换成这个:
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
我不知道为什么这些数字需要转换成浮点数(float),但如果不这样做就不行。这个方法有点脆弱;如果你把鼠标移动的距离乘以任何数,比如0.99或1.01,移动就会变得很奇怪。我怀疑鼠标的移动和画布的移动之间有某种反馈关系。它和滚动条的配合也不好;我想我们需要在滚动条移动时更新 pos_x 和 pos_y。总之,我也不太懂自己在做什么,毕竟我没有做过太多的图形界面编程。希望这些对你有帮助。
2
试着把画布的 xscrollincrement
和 yscrollincrement
属性的值设置为大于零的数。这些设置对应于你在调用 xview
和 yview
时使用的“单位”,比如说:self.canvas.xview("scroll",-1,"units")
。
根据官方的Tk文档,如果这些值是零(默认值),那么xview和yview会根据 "...如果[x,y]ScrollIncrement选项大于零,则按该单位调整,否则按窗口的[宽度,高度]的十分之一单位调整"来进行调整。