Tkinter bind double click not working as expected with multiple instances of the same object

33 views Asked by At

I'm trying to write a utility that will allow me to query a database, display the returned data and then allow the user to double click on one item to load/expand it. I've come up with the class below; each line will be an instance of this object, packed into a parent frame.

class PickerObject(tk.Frame):
    def __init__(self, parent, row_id, row_items, callbacks):
        super().__init__(parent)

        self.callbacks = callbacks

        self.configure(highlightbackground='black')
        self.configure(highlightthickness=1)
        self.rowconfigure(20, weight=1)
        self.columnconfigure(3, weight=1)

        self.row_id=row_id
        self.widgets = {}
        if self.row_id == 'new_prompt':
            self.widgets['prompt'] = ttk.Label(self, text=row_items)
            self.widgets['prompt'].grid(row=0, column=0, rowspan=2, sticky=tk.W, pady=10)
        else:
            for k, v in row_items.items():
                self.widgets[k] = ttk.Label(self, **v['text'])
                self.widgets[k].grid(padx=(0,25), **v['grid'])

        self.grid(in_=parent, padx=5, pady=(5, 0), sticky=tk.W + tk.E)
        self.bind('<Enter>', self.enter)
        self.bind('<Leave>', self.leave)
        self.bind('<Double-Button-1>', self.on_double_click)

    def enter(self, event=None):
        self.config(background='light blue')
        for widget in self.widgets:
            self.widgets[widget].config(background='light blue')

    def leave(self, event=None):
        self.config(background='light grey')
        for widget in self.widgets:
            self.widgets[widget].config(background='light grey')

    def on_double_click(self, event=None):
        self.callbacks['open'](self.row_id)

The code seems to work OK - the objects are being displayed as intended and the highlighting on mouse-over works, but the double click event only works on the first instance created.

I've tried googling with no success and I've read the Python and Tkinter documentation to try and understand what I'm doing wrong, but I just can't work it out.

Python 3.9.7, Tkinter 8.6

Edit:

As suggested, here's a minimum workable example - only difference is that, now, double click doesn't work at all.

import tkinter as tk
import tkinter.ttk as ttk


class Main(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        items = {}
        callback = {'open': self.open}

        f = tk.Frame(self)

        for i in range(5):
            items[i] = PickerObject(i, callback)
            items[i].pack(in_=f)

        f.pack()

    def open(self, id):
        print(f'ID = {id}')


class PickerObject(tk.Frame):
    def __init__(self, i, callback):
        super().__init__()

        self.id = i
        self.callbacks = callback

        self.widget = ttk.Label(self, text = f'Label: {i}')
        self.widget.pack()
        self.bind('<Enter>', self.enter)
        self.bind('<Leave>', self.leave)
        self.bind('<Double-Button-1>', self.on_double_click)

    def enter(self, event=None):
        self.config(background='light blue')
        self.widget.config(background='light blue')

    def leave(self, event=None):
        self.config(background='light grey')
        self.widget.config(background='light grey')

    def on_double_click(self, event=None):
        self.callbacks['open'](self.id)


if __name__ == '__main__':
    mw = tk.Tk()
    list_frame = Main(mw)
    list_frame.pack()
    mw.mainloop()

Edit:

For anyone interested, my full code, including database etc. is at https://github.com/tihnessa/almanac

0

There are 0 answers