【发布时间】:2025-11-30 00:15:01
【问题描述】:
我正在使用 tkinter 构建一个 GUI 应用程序,该应用程序需要一个用于建模的 CAD 界面,因此我使用了 tkinter 画布小部件。
我基于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()
结束编辑
【问题讨论】:
-
您找到解决问题的方法了吗?我也遇到过类似的问题。
-
我没有找到解决方案@Manish