Python tkinter Multilistbox自定义事件绑定问题

Python tkinter Multilistbox自定义事件绑定问题,python,tkinter,listbox,Python,Tkinter,Listbox,所以我的项目是关于显示数据库中的信息和图像。 其思路如下: 我有一个描述图像的数据库。一个表具有一般信息,如图像中包含的颜色,另一个表具有更详细的信息,如在何处可以找到该颜色,等等 启动搜索时,我希望打开两个窗口(ClassTwo和ClassTwo)。 与第一个只包含启动搜索按钮的窗口不同,我的完整应用程序包含用于筛选数据库请求的字段。当我启动该搜索时,我希望所有图像中都有绿色,因此ClassTwo将列出所有具有该颜色的图像以及其他元数据 ClassThree然后会列出所有包含相同颜色的区域,但

所以我的项目是关于显示数据库中的信息和图像。 其思路如下:

我有一个描述图像的数据库。一个表具有一般信息,如图像中包含的颜色,另一个表具有更详细的信息,如在何处可以找到该颜色,等等

启动搜索时,我希望打开两个窗口(
ClassTwo
ClassTwo
)。 与第一个只包含启动搜索按钮的窗口不同,我的完整应用程序包含用于筛选数据库请求的字段。当我启动该搜索时,我希望所有图像中都有绿色,因此
ClassTwo
将列出所有具有该颜色的图像以及其他元数据

ClassThree
然后会列出所有包含相同颜色的区域,但要更加详细,比如图像中的位置和大小等。 单击任一
多列表框
,我想打开一个显示图像的ImageViewer。 对于
ClassThree
,我还将直接突出显示我单击的区域,这样两个类都将有绑定到
多列表框的函数

我的问题是
列表框的绑定不正常。当我使用例如
image\u parts\u info\u lb.bind()
时,根本不会触发该函数。使用
image\u parts\u info\u lb.bind\u all()
时,仅触发最后一个
多列表框的功能

您可以在类的注释中找到
MultiListbox
的原始
Python2
版本

这是我的密码

import tkinter as tk

class MultiListbox(tk.Frame):
#original Python2 code here:
#https://www.oreilly.com/library/view/python-cookbook/0596001673/ch09s05.html
    def __init__(self, master, lists):
        tk.Frame.__init__(self, master)
        self.lists = []
        print(lists)
        for l,w in lists:
            frame = tk.Frame(self)
            frame.pack(side='left', expand='yes', fill='both')
            tk.Label(frame, text=l, borderwidth=1, relief='raised').pack(fill='x')
            lb = tk.Listbox(frame, width=w, borderwidth=0, selectborderwidth=0,
                         relief='flat', exportselection=False, height=16)
            lb.pack(expand='yes', fill='both')
            self.lists.append(lb)
            #commented out functions that were not necessary, as suggested in the comments
            #lb.bind('<B1-Motion>', self._select)
            lb.bind('<<ListboxSelect>>', self._select)
            #lb.bind('<Leave>', lambda e: 'break')
            lb.bind('<MouseWheel>', lambda e, s=self: s._scroll_mouse(e))
            #lb.bind('<Button-2>', lambda e, s=self: s._button2(e.x, e.y))
        frame = tk.Frame(self)
        frame.pack(side='left', fill='y')
        tk.Label(frame, borderwidth=1, relief='raised').pack(fill='x')
        sb = tk.Scrollbar(frame, orient='vertical', command=self._scroll)
        sb.pack(expand='yes', fill='y')
        self.lists[0]['yscrollcommand']=sb.set

    def _select(self, event):
        w = event.widget
        curselection = w.curselection()

        if curselection:
            self.selection_clear(0, self.size())
            self.selection_set(curselection[0])

    def _button2(self, x, y):
        for l in self.lists:
            l.scan_mark(x, y)
        return 'break'

    def _b2motion(self, x, y):
        for l in self.lists: l.scan_dragto(x, y)
        return 'break'

    def _scroll(self, *args):
        for l in self.lists:
            l.yview(*args)
        return 'break'

    def _scroll_mouse(self, event):
        for l in self.lists:
            l.yview_scroll(int(-1*(event.delta/120)), 'units')
        return 'break'

    def curselection(self):
        return self.lists[0].curselection()

    def delete(self, first, last=None):
        for l in self.lists:
            l.delete(first, last)

    def get(self, first, last=None):
        result = []
        for l in self.lists:
            result.append(l.get(first,last))
        if last: return apply(map, [None] + result)
        return result

    def index(self, index):
        self.lists[0].index(index)

    def insert(self, index, *elements):
        for e in elements:
            for i, l in enumerate(self.lists):
                l.insert(index, e[i])

    def size(self):
        return self.lists[0].size()

    def see(self, index):
        for l in self.lists:
            l.see(index)

    def selection_anchor(self, index):
        for l in self.lists:
            l.selection_anchor(index)

    def selection_clear(self, first, last=None):
        for l in self.lists:
            l.selection_clear(first, last)

    def selection_includes(self, index):
        return self.lists[0].selection_includes(index)

    def selection_set(self, first, last=None):
        for l in self.lists:
            l.selection_set(first, last)

class ClassOne:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.create_elements()
        self.frame.pack()

    def create_elements(self):
        search_button = tk.Button(self.frame, text = "Launch searches", command = \
        self.call_other_classes)
        search_button.grid(row = 2, column = 0, padx = 20, pady = 10)
        exit_button = tk.Button(self.frame, text = "Exit", command = self.master.quit)
        exit_button.grid(row = 2, column = 1, padx = 20, pady = 10)

    def call_other_classes(self):
        self.classes_list = []
        self.classes_list.append(ClassTwo(self.master))
        self.classes_list.append(ClassThree(self.master))

class ClassTwo:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(tk.Toplevel(self.master))
        self.frame.pack()
        self.create_elements()
        self.fill_image_listbox()       

    def create_elements(self):
        #placement of the custom MultiListbox
        self.available_images_lb = MultiListbox(self.frame, (('stuff1', 0), ('stuff1', 0), \
        ('stuff1', 0), ('stuff1', 0), ('stuff1', 0) ))
        self.available_images_lb.grid(row = 1, column = 1)
        self.available_images_lb.bind('<<ListboxSelect>>', self.print_stuff_two)
        #Button
        exit_button = tk.Button(self.frame, text = "Quit", command = self.frame.quit)
        exit_button.grid(row = 2, column = 1, padx = 20, pady = 10)


    def fill_image_listbox(self):
        image_info = [5*['ABCD'],5*['EFGH'],5*['JKLM'],5*['NOPQ'],5*['RSTU'], 5*['VWXY']]
        for item in image_info:
            self.available_images_lb.insert('end', item)

    def print_stuff_two(self, event):
        print('Class Two active')

class ClassThree:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(tk.Toplevel(self.master))
        self.create_elements()
        self.frame.pack()
        self.fill_imageparts_listbox()

    def create_elements(self):  
        self.image_parts_info_lb = MultiListbox(self.frame, (('stuff1', 0), ('stuff1', 0), \
        ('stuff1', 0), ('stuff1', 0), ('stuff1', 0) ))
        self.image_parts_info_lb.grid(row = 1, column = 1)
        self.image_parts_info_lb.bind('<<ListboxSelect>>', self.print_stuff_three)

    def fill_imageparts_listbox(self):
        self.image_parts_info_lb.delete(0, 'end')
        image_part_info = [5*['1234'],5*['5678'],5*['91011']]
        for item in image_part_info:
            self.image_parts_info_lb.insert('end', item)

    def print_stuff_three(self, event):
        print('Class Three active')     

def main():
    root = tk.Tk()
    root.title('Image Viewer')
    root.geometry('500x150+300+300')
    my_class_one = ClassOne(root)
    root.mainloop()


if __name__ == "__main__":
    main()
将tkinter作为tk导入
类MultiListbox(tk.Frame):
#原始Python2代码如下:
#https://www.oreilly.com/library/view/python-cookbook/0596001673/ch09s05.html
定义初始化(自、主、列表):
tk.Frame.\uuuuu init\uuuuuuu(自,主)
self.lists=[]
打印(列表)
对于列表中的l、w:
框架=传统框架(自身)
frame.pack(side='left',expand='yes',fill='both')
tk.Label(frame,text=l,borderwidth=1,relief='raised').pack(fill='x'))
lb=tk.Listbox(边框,宽度=w,边框宽度=0,选择边框宽度=0,
浮雕=平,导出选择=假,高度=16)
lb.pack(扩展class='yes',填充class='both')
self.lists.append(lb)
#按照注释中的建议,注释掉了不必要的函数
#lb.bind(“”,self.\u选择)
lb.bind(“”,self.\u选择)
#lb.bind('',lambda e:'断裂')
lb.bind(“”,lambda e,s=self:s._滚动_鼠标(e))
#lb.bind(“”,λe,s=自身:s._按钮2(e.x,e.y))
框架=传统框架(自身)
框架包装(侧面为左,填充为y)
tk.标签(边框,边框宽度=1,浮雕='凸起').pack(填充='x')
sb=tk.滚动条(框架,方向=垂直,命令=自滚动)
某人打包(扩展为“是”,填充为“y”)
self.lists[0]['yscrollcommand']=sb.set
def_选择(自身、事件):
w=事件.widget
curselection=w.curselection()
如果选择:
self.selection\u clear(0,self.size())
自选择集(选择[0])
def_按钮2(自身、x、y):
对于self.List中的l:
l、 扫描标记(x,y)
返回“中断”
def_b2运动(自、x、y):
对于self.list中的l:l.scan_dragto(x,y)
返回“中断”
def_滚动(自,*args):
对于self.List中的l:
l、 yview(*args)
返回“中断”
定义滚动鼠标(自身,事件):
对于self.List中的l:
l、 Y视图滚动(int(-1*(event.delta/120)),“单位”)
返回“中断”
选举(自选):
返回self.lists[0].curselection()
def delete(自我、第一、最后=无):
对于self.List中的l:
l、 删除(第一个,最后一个)
def get(自我、第一、最后=无):
结果=[]
对于self.List中的l:
result.append(l.get(first,last))
如果最后一个:返回应用(映射,[无]+结果)
返回结果
def索引(自我,索引):
self.lists[0]。索引(index)
def插入(自、索引、*元素):
对于元素中的e:
对于枚举(自我列表)中的i,l:
l、 插入(索引,e[i])
def大小(自身):
返回self.lists[0].size()
def见(自我,索引):
对于self.List中的l:
l、 见(索引)
def选择_锚(自身,索引):
对于self.List中的l:
l、 选择锚(索引)
def选择_清除(自身、第一个、最后一个=无):
对于self.List中的l:
l、 选择\u清除(第一个、最后一个)
def选择_包括(自身、索引):
返回self.lists[0]。选择内容包括(索引)
def选择_设置(自身、第一个、最后一个=无):
对于self.List中的l:
l、 选择集(第一个、最后一个)
一级:
定义初始(自我,主):
self.master=master
self.frame=tk.frame(self.master)
self.create_元素()
self.frame.pack()
def创建_元素(自):
搜索按钮=tk.按钮(self.frame,text=“启动搜索”,命令=\
self.call_其他_类)
搜索按钮网格(行=2,列=0,padx=20,pady=10)
退出按钮=tk.button(self.frame,text=“exit”,command=self.master.quit)
退出按钮网格(行=2,列=1,padx=20,pady=10)
def调用其他类(自身):
self.classes_list=[]
self.classes\u list.append(ClassTwo(self.master))
self.classes\u list.append(ClassThree(self.master))
第二类:
定义初始(自我,主):
self.master=master
self.frame=tk.frame(tk.top-level(self.master))
self.frame.pack()
self.create_元素()
self.fill\u image\u listbox()
def创建_元素(自):
#自定义Mu的放置
self.event_generate('<<MultiListboxSelect>>', when='tail')
class MultiListbox(tk.Frame):
    def __init__(self, master, lists):
        ...
        for l,w in lists:
            ...
            lb = tk.Listbox(frame, ...
            lb.bind('<<ListboxSelect>>', self._select)

    def _select(self, event):
        w = event.widget
        curselection = w.curselection()

        if curselection:
            self.event_generate('<<MultiListboxSelect>>', when='tail')
            ...

class ClassTwo:
    ...

    def create_elements(self):
        self.available_images_lb = MultiListbox(self.frame, ...
        ...
        self.available_images_lb.bind('<<MultiListboxSelect>>', self.print_stuff_two)
        ...

class ClassThree:
    ...

    def create_elements(self):  
        self.image_parts_info_lb = MultiListbox(self.frame, ...
        ...
        self.image_parts_info_lb.bind('<<MultiListboxSelect>>', self.print_stuff_three)