识别在Tkinter中点击的模型对象
我在一个画布上有很多重叠的形状,这些形状代表了一些不相关的背景物品。同时,我还有一些不重叠的圆圈,每个圆圈都是一个“洞”。每个“洞”的图像(圆圈)都有一个对应的“洞”对象,虽然在代码中并没有明确地关联它们。(顺便说一下,我希望能在这些对象之间建立一个逻辑上的关联,但我还没找到好的方法。)每个“洞”都是不同的,并且有不同的效果。
还有一个小圆形的“球”,可以被拖到任何一个“洞”里。我找到了如何拖放这个球的方法,具体可以参考这个问题。我需要找出这个球落进了哪个“洞”。
到目前为止,我找到的最好方法是:
创建一个字典,将“洞”图像中心的坐标映射到对应的“洞”对象。
给每个“洞”打个标签,像这样:
t=("hole", "hole_at_{}_{}".format(x, y))
在释放球的时候,执行以下操作:
def on_ball_release(self, event):
'''处理用户释放鼠标时的事件。'''# use small invisible rectangle and find all overlapping items items = self._canvas.find_overlapping(event.x - 10, event.y - 10, event.x + 10, event.y + 10) for item in items: # there should only be 1 overlapping hole if "hole" in self._canvas.gettags(item): # get the coordinates from the tag coords = tuple([int(i) for i in self._canvas.gettags(item)[1].replace("hole_at_", "").split("_")]) # get associated object using dictionary established before hole = self._hole_dict[coords] hole.process_ball() return
这样做看起来有点乱。我觉得应该有更聪明的方法来实现这个功能。
1 个回答
免责声明:我不使用Python,但很多关于Tkinter的问题可以通过我对Tcl/Tk的经验来解答。在这种情况下,我需要多花点时间来弄清楚我在Tcl中做的事情是否能简单地用Tkinter表示。
首先,我不会添加“标识标签”(hole_at_...
):如果我有与画布项目对应的模型对象,我会使用项目的id(画布在创建项目时返回的)作为索引,这样就可以直接找到与项目id对应的对象,而不需要解析标签。(如果我必须添加字符串标识符,即使我决定用坐标来生成它们,我也会使用那个字符串本身作为我的字典键,以避免再次解析。如果我们以后需要坐标,那就把它们作为hole
对象的属性来处理。)
其次,我会使用pathName find
的子命令,结合多个条件来查找被标记为hole
的项目(画布id),并且这个项目离给定的点最近(overlapping
适合用来忽略离任何洞太远的掉落,closest
则是为了在即使不太近的情况下也要使用最近的洞)。这里有个问题:Tkinter的画布支持在$pathName find
中使用多个条件吗?