在Python中减慢Tkinter Canvas滚动

时间:2011-03-24 20:01:51

标签: python scroll 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()

解答:

布莱恩·奥克利的答案就是我刚改变的伎俩:

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 :(得分: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

我不知道为什么你必须将这些数字转换为浮点数,但如果你不这样做则不行。它很脆弱;如果你将鼠标移动乘以任何东西,即使只是0.99或1.01,那么这个动作就会变得非常糟糕;我怀疑在鼠标移动和画布运动之间会有某种反馈。它也不能很好地与滚动条一起使用;我想我们必须在移动时更新pos_x和pos_y。正如我所说,不知道我在做什么;我没有做太多的GUI编程。无论如何,希望这会有所帮助。

答案 1 :(得分:2)

尝试将画布的xscrollincrementyscrollincrement属性的值设置为大于零的值。这些设置对应于您使用“单位”参数调用unitsxview时使用的yview(例如:self.canvas.xview("scroll",-1,"units")

根据官方Tk文档,如果这些值为零(默认值),xview和yview会调整“...以[x,y] ScrollIncrement选项为单位,如果它大于零,或者以窗口[宽度,高度]的十分之一为单位,否则为“

答案 2 :(得分:0)

尝试此操作,将拖动更改为仅使用计算值:

    self.canvas.yview("scroll",self._y-event.y,"units")
    self.canvas.xview("scroll",self._x-event.x,"units")

并将滚动增量更改为1.

现在您的图片应该点击&amp;与鼠标光标同步拖动,类似于流行的地图和文档查看器。