0

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

4
  • The posted code is incomplete. It is better to provide a minimal reproducible example. Commented Mar 28, 2024 at 9:12
  • 1
    It is because you bind double-click event on the frame and the label created inside covers all the space of the frame, so the double-click is on the label, not the frame. Commented Mar 28, 2024 at 9:53
  • Why do you use in_ option in .pack() instead of creating the instance of PickerObject as child of f. Commented Mar 28, 2024 at 9:55
  • Now bound the double click to the widgets (and the frame) and - surprise! - it works just fine. Thank you. As to why I'm using in_ i honestly don't know why. I'm sure there was a reason, but it's lost in the wastelands of my memory :) Commented Mar 28, 2024 at 10:05

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.