我如何将放大和缩小添加到以下脚本,我想将其绑定到鼠标滚轮。如果您正在Linux上测试此脚本,请不要忘记将MouseWheel事件更改为Button-4和Button-5。
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, xscrollincrement = 10, yscrollincrement = 10)
self.canvas.grid(row=0, column=0, sticky=N+S+E+W)
File = "PATH TO JPG PICTURE 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)
root.bind("<MouseWheel>",self.zoom)
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
def zoom(self,event):
if event.delta>0: print "ZOOM IN!"
elif event.delta<0: print "ZOOM OUT!"
root = Tk()
GUI(root)
root.mainloop()
据我所知,内置的Tkinter Canvas类缩放不会自动缩放图像。如果无法使用自定义窗口小部件,则可以缩放原始图像,并在调用缩放功能时将其替换在画布上。
下面的代码片段可以合并到您的原始类中。它执行以下操作:
Image.open()
。redraw()
计算缩放图像的功能,并将其添加到画布上,还删除了先前绘制的图像(如果有)。x and y
给该create_image
函数以显示图像位置如何随着鼠标移动而移动。您可以将其替换为自己的中心/偏移量计算。(已 更新 )代码:
class GUI:
def __init__(self, root):
# ... omitted rest of initialization code
self.canvas.config(scrollregion=self.canvas.bbox(ALL))
self.scale = 1.0
self.orig_img = Image.open(File)
self.img = None
self.img_id = None
# draw the initial image at 1x scale
self.redraw()
# ... rest of init, bind buttons, pack frame
def zoom(self,event):
if event.num == 4:
self.scale *= 2
elif event.num == 5:
self.scale *= 0.5
self.redraw(event.x, event.y)
def redraw(self, x=0, y=0):
if self.img_id:
self.canvas.delete(self.img_id)
iw, ih = self.orig_img.size
size = int(iw * self.scale), int(ih * self.scale)
self.img = ImageTk.PhotoImage(self.orig_img.resize(size))
self.img_id = self.canvas.create_image(x, y, image=self.img)
# tell the canvas to scale up/down the vector objects as well
self.canvas.scale(ALL, x, y, self.scale, self.scale)
更新 我做了一些不同比例的测试,发现resize / create_image正在使用大量内存。我在具有32GB RAM的Mac
Pro上使用540x375 JPEG进行了测试。这是用于不同比例因子的内存:
1x (500, 375) 14 M
2x (1000, 750) 19 M
4x (2000, 1500) 42 M
8x (4000, 3000) 181 M
16x (8000, 6000) 640 M
32x (16000, 12000) 1606 M
64x (32000, 24000) ...
reached around ~7400 M and ran out of memory, EXC_BAD_ACCESS in _memcpy
鉴于以上所述,一种更有效的解决方案可能是确定将在其中显示图像的视口的大小,围绕鼠标坐标中心计算裁剪矩形,使用rect裁剪图像,然后仅缩放裁剪的部分。这应该使用常量内存来存储临时图像。否则,您可能需要使用第三方Tkinter控件来为您执行此裁剪/窗口缩放。
Update 2 工作但过分简化的裁剪逻辑,只是为了让您入门:
def redraw(self, x=0, y=0):
if self.img_id: self.canvas.delete(self.img_id)
iw, ih = self.orig_img.size
# calculate crop rect
cw, ch = iw / self.scale, ih / self.scale
if cw > iw or ch > ih:
cw = iw
ch = ih
# crop it
_x = int(iw/2 - cw/2)
_y = int(ih/2 - ch/2)
tmp = self.orig_img.crop((_x, _y, _x + int(cw), _y + int(ch)))
size = int(cw * self.scale), int(ch * self.scale)
# draw
self.img = ImageTk.PhotoImage(tmp.resize(size))
self.img_id = self.canvas.create_image(x, y, image=self.img)
gc.collect()
问题内容: 这里是我想要的描述:在tkinter画布中绘制几何对象(在此为矩形)的集合,然后蜜蜂通过鼠标探索该画布。单击并拖动以移动画布,滚动放大和缩小。 使用本主题,我找到了单击和拖动部分:使用Mousewith-mouse 移动tkinter画布 我设法写了一些滚动缩放。移动和缩放都可以很好地分开工作。 问题 :如果移动然后放大,则变焦的焦点不再是光标所在的位置。 有什么建议吗? 这是一段要测
我正在做自己的画布抽屉项目,只是停留在放大/缩小功能上。在我的项目中,我使用缩放和平移来进行缩放,因为我想将所有画布及其元素保持在中心。在画了一点草图(不是数学天才)之后,我成功地画出了下面的公式用于翻译过程,因此缩放后画布将保持在它的视口的中间:旧的宽度和高度/ 2 -新的宽度和高度(这是旧的宽度和高度乘以比例步长,在我的例子中是1.1)/2。从逻辑上讲,这应该行得通。但是在尝试了几次放大和缩小
问题内容: 我正在尝试制作一个Python程序,您可以在其中移动小部件。 这是我的代码: 但是,这会出现小故障,并且小部件来回跳转。 谢谢! 问题答案: 您观察到的行为是由于事件的坐标相对于拖动的小部件而引起的。用 相对 坐标更新小部件的位置(在 绝对 坐标中)显然会导致混乱。 __ 为了解决这个问题,我使用了和函数(允许将相对坐标转换为绝对坐标),并使用事件来确定拖动开始时光标在小部件上的位置。
问题内容: 我正在尝试模仿动画和以下浮动操作按钮的颜色更改。 浮动操作按钮的工作方式是关闭白色,打开蓝色。 但是,我在动画和更改颜色方面一直不成功。 这些是我尝试执行此操作的尝试,您可以看到我已经注释掉了我尝试执行此操作的所有不同方式。 这是我的代码: Many thanks for any suggestions. 问题答案: 此动画有两个阶段。第一个缩放X和Y轴,第二个缩小它。因此,我们可以将
我的出发点如下: FXML: Java FX控制器:
我的JavaFX 8应用程序中有以下代码,用于控制添加到场景中的画布元素的变换比例: 问题是,就像它所说的,附加到转换中,并且由于浮点精度,每次滚动时缩放级别都会略有不同。 由于某些原因,我必须修改图形上下文转换,而不是直接修改画布(换句话说,要进行翻译,我必须使用transform.setTx(…) 而不是画布。setTranslateX(…) 。 解决方案是设置转换的尺度,同时考虑枢轴点(即鼠