【问题标题】:Tkinter - Find closest object of a certain typeTkinter - 查找某种类型的最近对象
【发布时间】:2014-12-03 20:52:31
【问题描述】:

我在这里遇到的问题是我无法找到某种类型的最近对象。最好把代码给你,让你明白我的意思:

from Tkinter import *
root = Tk()
f=Frame(root)
f.grid()
w=Canvas(f)
def identify(event): ## this should identify the tag near to click
    item = w.find_closest(event.x, event.y)[0]
    print item
line1=w.create_line(50,50,150,150, width=5, tags="line")
line2=w.create_line(100,100,100,350, width=3, tags="line")
line3=w.create_line(150,150,150,450, width=3, tags = "line")
w.grid(row=0, column=0)
w.bind("<ButtonRelease-1>", identify)

u=Frame(f)
u.grid(row=0, column=1)
root.mainloop()

正如您在此处看到的,您可以单击屏幕上的任意位置,它将返回最近的对象。这是我想要实现的,但屏幕上有其他我希望被忽略的对象。我可以通过使用 tags 来做到这一点,但这里的问题是您出于某种原因需要单击实际对象。此代码用于显示我的问题。我的实际代码是河内塔游戏,我的目标是找到最近的极点,以便磁盘能够捕捉到它,但是如果在移动磁盘之前不点击每个极点,我就无法找到最近的极点。

这是显示我的问题的代码。注意:我只是将“w.bind(””,identify)”改为“w.tag_bind(“line”,“”,identify)”

from Tkinter import *
root = Tk()
f=Frame(root)
f.grid()
w=Canvas(f)
def identify(event): ## this should identify the tag near to click
    item = w.find_closest(event.x, event.y)[0]
    print item
line1=w.create_line(50,50,150,150, width=5, tags="line")
line2=w.create_line(100,100,100,350, width=3, tags="line")
line3=w.create_line(150,150,150,450, width=3, tags = "line")
w.grid(row=0, column=0)
w.tag_bind("line", "<ButtonRelease-1>", identify)

u=Frame(f)
u.grid(row=0, column=1)
root.mainloop()

【问题讨论】:

  • 将事件处理程序绑定到标签会说“只有在我点击标记的项目时才会触发”,这就是你所说的发生。不要问你不想要的东西;-)。还有什么“壁橱杆”?
  • 我认为最接近空间中的点击点。我认为要求用户单击或靠近钉子顶部没有问题,这样钉子将是最接近的。如果项目编号不在 [1,3] 中,请忽略点击。
  • 您的问题的一般答案可能是两个画布相互叠放(使用 .place()),一个带有点击绑定和特殊项目。
  • @TerryJanReedy:如果两幅画布在彼此之上,您将看不到下面的那幅。这不是一个好的解决方案。
  • @BryanOakley 抱歉,我认为它们可以变得透明。哦,好吧。

标签: python tkinter tags bind tkinter-canvas


【解决方案1】:

对你来说有点晚了,但也许对其他人有用......

我今天刚遇到同样的问题,并使用第二个 Canvas 解决了这个问题,其中包含所需项目的副本。
这幅画布从未印刷过。这有点棘手,但我找不到更好的。

draft = Canvas(w) # if w is deleted, the draft is deleted


draft.delete(ALL) # if you use the fake canvas for other uses

concerned = w.find_withtag("line") # what you want

for obj in concerned: # copy on draft

    # first, get the method to use
    if w.type(obj) == "line": create = draft.create_line
    # use "elif ..." to copy more types of objects
    else: continue

    # copy the element with its attributes
    config = {opt:w.itemcget(obj, opt) for opt in w.itemconfig(obj)}
    config["tags"] = str(obj) # I can retrieve the ID in "w" later with this trick
    create(*w.coords(obj), **config)

# use coordinates relative to the canvas
x = w.canvasx(event.x)
y = w.canvasy(event.y)

item = draft.find_closest(x,y) # ID in draft (as a tuple of len 1)
if item: item = int( draft.gettags(*item)[0] ) # ID in w
else: item = None # closest not found

print(item)

我希望我可以使用create(*w.coords(obj), **w.itemconfig(obj)),但是itemconfig 不带参数返回一个其值不能被重用的字典。

关于物品副本:https://stackoverflow.com/a/20278179/7420421

顺便说一下,我用的是python 3,不知道python 2能不能用。

【讨论】:

    猜你喜欢
    • 2020-08-07
    • 1970-01-01
    • 2022-08-11
    • 2011-09-28
    • 2019-04-02
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 2012-06-21
    相关资源
    最近更新 更多