【发布时间】:2013-09-23 22:05:30
【问题描述】:
背景:
我有一个使用 Tkinter 作为 GUI 基础的程序。该程序有一个画布,其中填充了大量对象。目前,为了移动屏幕上的所有对象,我只是将一个移动函数绑定到标签“all”,这当然会移动屏幕上的所有对象。但是,跟踪 所有 画布对象的位置对我来说至关重要 - 即在每次移动后我都会记录新位置,这似乎不必要地复杂。
问题:
仅使用鼠标(不使用滚动条)有效滚动/拖动整个画布(屏幕大小的几倍)的最佳方法是什么?
我的尝试:
我已经实现了滚动条,并找到了几个设置滚动条的指南,但没有一个能满足这一特殊要求。
不使用的滚动条方法示例:
from Tkinter import *
class Canvas_On:
def __init__(self, master):
self.master=master
self.master.title( "Example")
self.c=Canvas(self.master, width=find_res_width-20, height=find_res_height, bg='black', scrollregion=(0,0,5000,5000))
self.c.grid(row=0, rowspan=25, column=0)
self.c.tag_bind('bg', '<Control-Button-1>', self.click)
self.c.tag_bind('bg', '<Control-B1-Motion>', self.drag)
self.c.tag_bind('dot', '<Button-1>', self.click_item)
self.c.tag_bind('dot', '<B1-Motion>', self.drag_item)
draw=Drawing_Utility(self.c)
draw.drawer(self.c)
def click(self, event):
self.c.scan_mark(event.x, event.y)
def drag(self, event):
self.c.scan_dragto(event.x, event.y)
def click_item(self, event):
self.c.itemconfigure('dot 1 text', text=(event.x, event.y))
self.drag_item = self.c.find_closest(event.x, event.y)
self.drag_x, self.drag_y = event.x, event.y
self.c.tag_raise('dot')
self.c.tag_raise('dot 1 text')
def drag_item(self, event):
self.c.move(self.drag_item, event.x-self.drag_x, event.y-self.drag_y)
self.drag_x, self.drag_y = event.x, event.y
class Drawing_Utility:
def __init__(self, canvas):
self.canvas=canvas
self.canvas.focus_set()
def drawer(self, canvas):
self.canvas.create_rectangle(0, 0, 5000, 5000,
fill='black', tags='bg')
self.canvas.create_text(450,450, text='', fill='black', activefill='red', tags=('draggable', 'dot', 'dot 1 text'))
self.canvas.create_oval(400,400,500,500, fill='orange', activefill='red', tags=('draggable', 'dot', 'dot 2'))
self.canvas.tag_raise(("dot"))
root=Tk()
find_res_width=root.winfo_screenwidth()
find_res_height=root.winfo_screenheight()
run_it=Canvas_On(root)
root.mainloop()
我的特殊问题
我的程序生成所有画布对象坐标,然后绘制它们。这些对象以各种模式排列,但至关重要的是,它们必须“知道”彼此的位置。当使用@abarnert 提供的方法在画布上移动时,以及我编写的移动所有画布对象的类似方法时,出现的问题是每个对象都“认为”它位于绘制对象之前生成的画布坐标处。例如,如果我将画布向左拖动 50 像素并单击程序中的一个对象,它会向右跳 50 像素回到它的原始位置。我对此的解决方案是编写一些代码,在释放鼠标按钮时,记录最后一个位置并更新每个对象的坐标数据。但是,我正在寻找一种方法来删除这最后一步——我希望有一种方法可以移动画布,使对象位置是绝对的,并假设类似于“滚动”功能的功能可以做到这一点。我意识到我在这里闲逛了,但是我在上面的示例中添加了几行代码,这些代码突出了我的问题——通过移动画布,您可以看到坐标发生了变化。再次感谢。
【问题讨论】:
-
我不太清楚你想要什么。在不使用滚动条的情况下如何在画布上滚动?您希望能够单击背景上的任意位置并拖动,就像在某些照片编辑器中一样?还是有什么不同?
-
无论如何,如果您有任何知道如何滚动其内容的小部件,则不需要滚动条。您编写的用于将滚动条连接到小部件的代码,只需在您想要滚动时直接运行该代码。例如,如果您正在执行
vscrollbar['command'] = widget.yview,只需使用适当的参数调用widget.yview。 (如果您可以向我们展示您实际的基于滚动条的代码,最好是 tiny, stripped-down example program,我可以向您展示如何编写显式滚动,而不是含糊其辞。) -
您好,感谢您的回复!我在问题中添加了一个剥离示例。
-
@BryanOakley:我认为他的观点是,因为他不知道如何滚动画布,所以他通过向相反方向移动项目来伪装它。
-
@MarkyD43:你的困惑可能是我的错——我的上一个版本有一个错误,我忘记了
canvasx/canvasy-映射drag_item中的坐标。我现在已经解决了。
标签: python python-2.7 tkinter tkinter-canvas