在Python中减慢Tkinter画布滚动速度

0 投票
3 回答
2792 浏览
提问于 2025-04-16 14:21

基本上,我有以下代码可以正常工作,但我找不到方法来减慢我的画布视图拖动的速度,现在拖动得太快,无法在我的应用中正常使用。这只是一个小例子,展示了我正在尝试解决的问题:

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

试着把画布的 xscrollincrementyscrollincrement 属性的值设置为大于零的数。这些设置对应于你在调用 xviewyview 时使用的“单位”,比如说:self.canvas.xview("scroll",-1,"units")

根据官方的Tk文档,如果这些值是零(默认值),那么xview和yview会根据 "...如果[x,y]ScrollIncrement选项大于零,则按该单位调整,否则按窗口的[宽度,高度]的十分之一单位调整"来进行调整。

撰写回答