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

python tkinter如何使用canvas查找特定列表中最近的项,python,tkinter,canvas,find,Python,Tkinter,Canvas,Find,我知道如何使用canvas.find_nextest()方法在画布中找到最近的项,但我希望它能找到紧跟在特定信条后面的最近的项,就像它在列表中一样 例如: 从tkinter导入* tk=tk() 画布=画布(tk,宽度=1000,高度=100) item1=画布。创建矩形(0,0,50,50) item2=画布。创建矩形(30,30,80,80) item3=画布。创建矩形(200200300300) 项目列表=[item1,item2] def查找最近的项目(事件): item=canvas.

我知道如何使用canvas.find_nextest()方法在画布中找到最近的项,但我希望它能找到紧跟在特定信条后面的最近的项,就像它在列表中一样

例如:

从tkinter导入*
tk=tk()
画布=画布(tk,宽度=1000,高度=100)
item1=画布。创建矩形(0,0,50,50)
item2=画布。创建矩形(30,30,80,80)
item3=画布。创建矩形(200200300300)
项目列表=[item1,item2]
def查找最近的项目(事件):
item=canvas.find_最近(event.x,event.y)
canvas.bind(“,查找最近的项目)

在这段代码中,我希望如果我点击项目3,它不会找到它,因为它不在“项目列表”中,而且它会找到项目3之后最接近的项目,我不知道有什么好方法可以做到这一点。我可以通过制作一个自定义画布小部件来破解一个解决方案,该小部件保留一个单独的区域用于查找内容,这样我就可以定义一个
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()
将tkinter作为tk导入
从类型导入方法类型
类FindCanvas(tk.Canvas):
"""
一种画布类型,其中的项可以不使用find方法
包括查找、查找上面的、查找所有、查找下面的、查找最近的、,
查找封闭、查找重叠、查找带标记
"""
定义初始化(自,主=无,**kwargs):
super().\uuuu init\uuuu(主控,**kwargs)
self.finder=tk.Canvas(主控,**kwargs)
#在这两种情况下都需要调用这些方法
对于“移动”、“删除”、“协调”、“dchars”中的方法名:
def func(self,*args,methodname=methodname,**kwargs):
getattr(self.finder,methodname)(*args,**kwargs)
返回getattr(super(),methodname)(*args,**kwargs)
setattr(self,methodname,MethodType(func,self))
def查找(自我、*args、**kwargs):
返回self.finder.find(*args,**kwargs)
def_create(self、itemType、args、kw):
kwargs=千瓦
如果不是kw.pop(“finditem”,True):
kwargs=dict(list(kw.items())+[('state','hidden')))#是的,我知道3.9
self.finder.\u创建(itemType、args、kwargs)
return super()。_create(itemType,args,kw)
###演示用途:
def查找最近的项目(事件):
item=canvas.find_最近(event.x,event.y)
lbl.config(text=“最近的项目是项目编号”+str(项目))
root=tk.tk()
画布=FindCanvas(根,宽度=400,高度=400)
canvas.pack()
item1=画布。创建矩形(0,0,50,50)
item2=画布。创建矩形(30,30,80,80)
item3=canvas.create_矩形(200200300300findItem=False)
item4=canvas.create_oval(30300100400,finditem=False)
item5=画布。创建矩形(6034080380)
canvas.bind(“,查找最近的项目)
lbl=传统标签(根)
lbl.pack()
tk.mainloop()

顺便说一句,使用tkinter import*中的
tk=tk()
是非常错误的、非常规的,可能会破坏此代码。按照我展示的标准方法来做。

我不知道有什么好方法可以做到这一点。我可以通过制作一个自定义画布小部件来破解一个解决方案,该小部件保留一个单独的区域用于查找内容,这样我就可以定义一个
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()
将tkinter作为tk导入
从类型导入方法类型
类FindCanvas(tk.Canvas):
"""
一种画布类型,其中的项可以不使用find方法
包括查找、查找上面的、查找所有、查找下面的、查找最近的、,
查找封闭、查找重叠、查找带标记
"""
定义初始化(自,主=无,**kwargs):
super().\uuuu init\uuuu(主控,**kwargs)
self.finder=tk.Canvas(主控,**kwargs)
#在这两种情况下都需要调用这些方法
对于“移动”、“删除”、“协调”、“dchars”中的方法名:
def func(self,*args,methodname=methodname,**kwargs):
getattr(self.finder,methodname)(*args,**kwargs)
返回getattr(super(),methodname)(*args,**kwargs)
setattr(self,methodname,MethodType(func,self))
def查找(自我、*args、**kwargs):
返回self.finder.find(*args,**kwargs)
def_create(self、itemType、args、kw):
kwargs=千瓦
如果不是kw.pop(“finditem”,True):
kwargs=dict(list(kw.items())+[('state','hidden')))#是的,我知道3.9
self.finder.\u创建(itemType、args、kwargs)
return super()。_create(itemType,args,kw)
###演示用途:
def查找最近的项目(事件):
item=canvas.find_最近(event.x,event.y)
lbl.config(text=“最近的项目是项目编号”+str(项目))
root=tk.tk()
画布=FindCanvas(根,宽度=400,高度=400)
canvas.pack()
item1=画布。创建矩形(0,0,50,50)
item2=画布。创建矩形(30,30,80,80)
item3=canvas.create_矩形(200200300300findItem=False)
item4=canvas.create_oval(30300100400,finditem=False)
item5=画布。创建矩形(6034080380)
canvas.bind(“,查找最近的项目)
lbl=传统标签(根)
lbl.pack()
tk.mainloop()

顺便说一句,使用tkinter import*
中的
tk=tk()
是非常错误的、非常规的,可能会破坏此代码。按照我展示的标准方式做。

好的,谢谢。好的,谢谢。