python-tkinter如何使用canvas查找特定列表中最接近的项



我知道如何使用canvas.find_closest((方法在canvas中找到最接近的项,但我希望它能像在列表中一样找到特定creteria后面的最接近项

例如:

from tkinter import *
tk=Tk()
canvas=Canvas(tk, width=1000, height=100)
item1=canvas.create_rectangle(0, 0, 50, 50)
item2=canvas.create_rectangle(30, 30, 80, 80)
item3=canvas.create_rectangle(200, 200, 300, 300)
list_of_items=[item1, item2]
def find_closest_item(event):
item=canvas.find_closest(event.x, event.y)

canvas.bind("<Button-1>", find_closest_item)

在这个代码中,我希望如果我点击item3,它不会找到它,因为它不在";项目列表";并且它将在项目3 之后找到最接近的

我不知道有什么好方法可以做到这一点。我可以通过制作一个自定义的Canvas小部件来破解一个解决方案,该小部件保留了一个单独的区域来查找内容,这样我就可以定义一个finditem参数。

import tkinter as tk
from types import MethodType
class FindCanvas(tk.Canvas):
"""
A type of Canvas where items can be exempted from find methods
including find, find_above, find_all, find_below, find_closest,
find_enclosed, find_overlapping, find_withtag
"""
def __init__(self, master=None, **kwargs):
super().__init__(master, **kwargs)
self.finder = tk.Canvas(master, **kwargs)
# these methods need to be called in both instances
for methodname in ("move", "delete", "coords", "dchars"):
def func(self, *args, methodname=methodname, **kwargs):
getattr(self.finder, methodname)(*args, **kwargs)
return getattr(super(), methodname)(*args, **kwargs)
setattr(self, methodname, MethodType(func, self))
def find(self, *args, **kwargs):
return self.finder.find(*args, **kwargs)
def _create(self, itemType, args, kw):
kwargs = kw
if not kw.pop("finditem", True):
kwargs = dict(list(kw.items()) + [('state', 'hidden')]) # yes, I know about 3.9
self.finder._create(itemType, args, kwargs)
return super()._create(itemType, args, kw)
### DEMO use:
def find_closest_item(event):
item=canvas.find_closest(event.x, event.y)
lbl.config(text="Closest item is item number "+str(item))
root=tk.Tk()
canvas=FindCanvas(root, width=400, height=400)
canvas.pack()
item1=canvas.create_rectangle(0, 0, 50, 50)
item2=canvas.create_rectangle(30, 30, 80, 80)
item3=canvas.create_rectangle(200, 200, 300, 300, finditem=False)
item4=canvas.create_oval(30, 300, 100, 400, finditem=False)
item5=canvas.create_rectangle(60, 340, 80, 380)
canvas.bind("<Button-1>", find_closest_item)
lbl = tk.Label(root)
lbl.pack()
tk.mainloop()

顺便说一句,使用from tkinter import *tk=Tk()是非常有缺陷的,非常规的,可能会破坏这个代码。按照我展示的标准方式去做。

最新更新