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

发布于 2024-09-28 03:24:03 字数 160 浏览 6 评论 0原文

我正在使用 Python 和 tkinter。我有一个 Canvas 小部件,它将仅显示一张图像。大多数情况下,图像会大于画布尺寸,但有时会更小。我们只关注第一种情况(图像比画布大)。

我想将画布滚动到我已经计算过的绝对位置(以像素为单位)。我怎样才能做到这一点?

I'm using Python and tkinter. I have a Canvas widget that will display just one image. Most times the image will be larger than the canvas dimensions, but sometimes it will be smaller. Let's just focus on the first case (image larger than canvas).

I want to scroll the canvas to an absolute position that I have already calculated (in pixels). How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心如狂蝶 2024-10-05 03:24:03

经过大约半个小时的尝试,我得到了另一个似乎更好的解决方案:

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)

After trying for around half hour, I got another solution that seems better:

self.canvas.xview_moveto(float(scroll_x+1)/img_width)
self.canvas.yview_moveto(float(scroll_y+1)/img_height)
  • img_width and img_height are the dimensions of the image. In other words, they are the full scrollable area.

  • scroll_x and scroll_y are the coordinates of the desired top-left corner.

  • +1 is a magic value to make it work precisely (but should be applied only if scroll_x/y is non-negative)

  • Note that the current widget dimension is not needed, only the dimension of the contents.

This solution works very well even if the image is smaller than the widget size (and thus the scroll_x/y can be negative).

EDIT: improved version:

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)
可遇━不可求 2024-10-05 03:24:03

这就是我已经做过的:

# 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

但是......正如你所看到的......它非常hackish和丑陋。对于本应简单的事情来说,有太多的解决方法。 (加上我需要添加的神奇 +1 ,否则它将相差一)

还有其他人有另一个更好、更干净的解决方案吗?

This is what I have already done:

# 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

But... As you can see... it's very hackish and ugly. To much workaround for something that should be simple. (plus that magic +1 I was required to add, or it would be off-by-one)

Does anyone else have another better and cleaner solution?

爱已欠费 2024-10-05 03:24:03

在 tkinter 中,您可以获得 PhotoImage 文件的 widthheight。您可以在使用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)

In tkinter you can get the width and height of a PhotoImagefile. You can just call it when you use 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)
我爱人 2024-10-05 03:24:03

我通过使用 self.canvas.scan_dragto(x, y) 找到了这个解决方案

编辑:我开发了一个可以滚动、缩放和旋转图像的界面。让我们从我的界面中提取代码。

当我想保存图像的当前位置时,我使用以下命令:

# 1) Save image position
x0canvas = -self.canvas.canvasx(0)
y0canvas = -self.canvas.canvasy(0)
x0, y0 = self.canvas.coords(text)
ximg = x0
yimg = y0

# 2) Restore image position (for example: after a load)
self.text = canvas.create_text(ximg, yimg, anchor='nw', text='')
self.xyscroll(x0canvas, y0canvas) 

# Rotate and zoom image 
image = Image.open('fileImg.jpg')
..
imageMod = image.resize(new_size)
if rotate != 0:
    imageMod = imageMod.rotate(rotate)
imagetk = ImageTk.PhotoImage(imageMod)
imageid = canvas.create_image(canvas.coords(text), anchor='nw', image=imagetk)

I found this solution by using self.canvas.scan_dragto(x, y)

Edit: I develop an interface which can scroll, zoom, and rotate an image. Let's extract from my interface the code.

When I want to save the current position of image I use this:

# 1) Save image position
x0canvas = -self.canvas.canvasx(0)
y0canvas = -self.canvas.canvasy(0)
x0, y0 = self.canvas.coords(text)
ximg = x0
yimg = y0

# 2) Restore image position (for example: after a load)
self.text = canvas.create_text(ximg, yimg, anchor='nw', text='')
self.xyscroll(x0canvas, y0canvas) 

# Rotate and zoom image 
image = Image.open('fileImg.jpg')
..
imageMod = image.resize(new_size)
if rotate != 0:
    imageMod = imageMod.rotate(rotate)
imagetk = ImageTk.PhotoImage(imageMod)
imageid = canvas.create_image(canvas.coords(text), anchor='nw', image=imagetk)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文