我在这里的预测是我无法找到某种类型的最接近的对象。最好是我给你代码,让你明白我的意思:
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()
正如你在这里看到的,你可以点击屏幕上的任意位置,它将返回最近的对象。这就是我想要实现的目标,但屏幕上还有其他我希望被忽略的对象。我能够通过使用标签来做到这一点,但这里的问题是出于某种原因您需要单击实际对象。此代码用于显示我的问题。我的实际代码是河内塔游戏,我的目标是找到最近的极点,以便磁盘能够捕捉到它,但是如果不在移动磁盘之前单击每个极点,我就无法找到最近的极点。
这是显示我的问题的代码。注意:我只将"w.bind(",识别)"更改为"w.tag_bind("行",",识别)"
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()
对你来说有点晚了,但也许对其他人有用......
我今天刚刚遇到了同样的问题,并使用第二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
返回一个值不能重用的字典。
:复制 Tkinter 画布项目
顺便说一句,我使用了python 3,我不知道它是否适用于python 2。
您可以通过 w.type(item)
确定identify()
中选择对象的类型。由于游戏中的线可能不是杆子,因此您可以添加标签来标识哪些线是杆子。
这就是我的意思(请注意这是Python 3代码,但同样的想法在Python 2.x中也有效):
import tkinter as tk
root = tk.Tk()
f = tk.Frame(root)
f.grid()
w = tk.Canvas(f)
def identify(event):
item = w.find_closest(event.x, event.y)[0]
print(f'type of item closest to click: {w.type(item)}')
# Check tags to see if it's a pole.
if w.type(item) == 'line': # Canvas line?
for tag in w.gettags(item): # Check its tags.
if tag.startswith('pole'):
print(f' You clicked near pole {w.gettags(item)[1]}')
break
else:
print(' You did not click near a pole')
line1 = w.create_line(50,50,150,150, width=5)
line2 = w.create_line(100,100,100,350, width=3, tags='pole 1')
line3 = w.create_line(150,150,150,450, width=3, tags='pole 2')
w.grid(row=0, column=0)
w.bind('<ButtonRelease-1>', identify)
u = tk.Frame(f)
u.grid(row=0, column=1)
root.mainloop()