如何将tkinter画布滚动到绝对位置?

3 投票
4 回答
6394 浏览
提问于 2025-04-16 05:36

我正在使用 Pythontkinter。我有一个 Canvas 组件,它只会显示一张图片。大多数情况下,这张图片会比画布的大小要大,但有时候它会小一点。我们先只讨论第一种情况,也就是图片比画布大。

我想把画布滚动到一个我已经计算好的绝对位置(以像素为单位)。我该怎么做呢?

4 个回答

0

在tkinter中,你可以获取一个PhotoImage文件的宽度高度。当你使用canvas.create_image的时候,可以直接调用这个功能。

imgrender = PhotoImage(file="something.png")
##Other canvas and scrollbar codes here...
canvas.create_image((imgrender.width()/2),(imgrender.height()/2), image=imgrender)
## The top left corner coordinates is (width/2 , height/2)
0

这是我已经做的事情:

# Little hack to scroll by 1-pixel increments.
oldincx = self.canvas["xscrollincrement"]
oldincy = self.canvas["yscrollincrement"]
self.canvas["xscrollincrement"] = 1
self.canvas["yscrollincrement"] = 1
self.canvas.xview_moveto(0.0)
self.canvas.yview_moveto(0.0)
self.canvas.xview_scroll(int(scroll_x)+1, UNITS)
self.canvas.yview_scroll(int(scroll_y)+1, UNITS)
self.canvas["xscrollincrement"] = oldincx
self.canvas["yscrollincrement"] = oldincy

但是……你看,这种做法很笨拙,也不美观。为了实现一个简单的功能,我用了太多的变通方法。(还有那个神奇的 +1,如果不加上去就会出现偏差)

有没有其他人有更好、更简洁的解决方案呢?

5

经过大约半个小时的尝试,我找到了一个看起来更好的解决方案:

self.canvas.xview_moveto(float(scroll_x+1)/img_width)
self.canvas.yview_moveto(float(scroll_y+1)/img_height)
  • img_widthimg_height 是图片的宽度和高度。换句话说,它们代表了整个可以滚动的区域。

  • scroll_xscroll_y 是你想要的左上角的坐标。

  • +1 是一个 魔法 值,用来让它更精确地工作(但只有在 scroll_x/y 是非负数时才应该使用)。

  • 注意,当前小部件的尺寸并不需要,只需要内容的尺寸。

这个解决方案即使在图片比小部件小的情况下也能很好地工作(因此 scroll_x/y 可能是负数)。

编辑:改进版本:

offset_x = +1 if scroll_x >= 0 else 0
offset_y = +1 if scroll_y >= 0 else 0
self.canvas.xview_moveto(float(scroll_x + offset_x)/new_width)
self.canvas.yview_moveto(float(scroll_y + offset_y)/new_height)

撰写回答