我正在使用tkinter构建GUI应用程序,应用程序需要一个CAD界面进行建模,所以我使用了tkinter canvas小部件。
我实现了使用基于this thread的鼠标移动和缩放画布的方法。我遇到的问题是缩放画布会改变其上对象的坐标(有时坐标会从正变为负)。因此,如果我使用;
在画布上绘制矩形 self.canvas.create_rectangle(0, 5, 75, 100, outline="black", fill="blue")
self.canvas.create_text(100,125, anchor="nw", text="Click and drag to move the canvas\nScroll to zoom.")
然后缩放或移动和缩放画布,并使用;
绘制另一个矩形 self.canvas.create_rectangle(75, 5, 200, 100, outline="black", fill="red")
我希望看到类似的东西;
但我得到了这个;
无论如何要在tkinter中解决这个问题吗?
修改
我已经用Bryan的答案更新了我的代码。我能够跟踪self.scale
属性中的比例因子,但偏移量(在self.offset
属性中跟踪)仍然是错误的。我无法计算重复变焦的累积偏移量。新的矩形正确缩放(尺寸方面),但偏移/位置仍然关闭。
这是我目前的代码;
import Tkinter as tk
class CAD(tk.Frame):
def __init__(self, root):
tk.Frame.__init__(self, root)
self.scale = 1
self.offset = [0, 0]
self.current_scale = [self.offset[0], self.offset[1], self.scale, self.scale]
self.canvas = tk.Canvas(self, width=400, height=350, background="bisque")
self.canvas.pack()
#Plot on the canvas
self.rect = self.canvas.create_rectangle(0, 5, 75, 100, outline="black", fill="blue")
self.canvas.create_text(100,125, anchor="nw", text="""
Left click and drag to move the canvas
Scroll to zoom
Right click to draw rectangle""")
# Mouse bindings to the canvas
self.canvas.bind("<ButtonPress-1>", self.move_start)
self.canvas.bind("<B1-Motion>", self.move_move)
self.bind_all("<MouseWheel>", self.zoom)
self.canvas.bind("<ButtonPress-3>", self.draw)
# move
def move_start(self, event):
self.canvas.scan_mark(event.x, event.y)
def move_move(self, event):
self.canvas.scan_dragto(event.x, event.y, gain=1)
# zoom
def zoom(self, event):
true_x = self.canvas.canvasx(event.x)
true_y = self.canvas.canvasy(event.y)
if (event.delta > 0):
sc = 1.1
elif (event.delta < 0):
sc = 0.9
self.canvas.scale("all", true_x, true_y, sc, sc)
self.scale *= sc
self.offset = [sum(x) for x in zip(self.offset, [true_x, true_y])]
self.current_scale = [self.offset[0], self.offset[1], self.scale, self.scale]
def draw(self, event):
new_item = self.canvas.create_rectangle(75, 5, 200, 100, outline="black", fill="red")
self.canvas.scale(new_item, *self.current_scale)
if __name__ == "__main__":
root = tk.Tk()
CAD(root).pack(fill="both", expand=True)
root.mainloop()
结束编辑
答案 0 :(得分:2)
说明问题的一种方法是:
要使对象对齐,您需要根据当前的转换集转换任何新项的坐标。
假设您知道当前比例因子是什么,您只需将缩放应用于您创建的任何新项目。
例如,以下代码产生的结果就像您在问题中描述的那样,即使第二个矩形在第一个缩放后创建了第二个矩形,它们也会对齐:
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=400, background="bisque")
canvas.pack(fill="both", expand=True)
# start with one rectangle
canvas.create_rectangle(0, 5, 75, 100, outline="black", fill="blue")
# scale it, and save the scale
current_scale = (0, 0, 1.5, 1.5)
canvas.scale("all", *current_scale)
# add a new item, and apply the same scale to it
new_item = canvas.create_rectangle(75, 5, 200, 100, outline="black", fill="red")
canvas.scale(new_item, *current_scale)
root.mainloop()