Home > database >  Binding to widget
Binding to widget

Time:11-12

I am having problems binding key events to TkInter widgets. I have tried many example from the websites, but with no luck. I notice that none of the examples are using classes. I am defining my GUI inside a class; could that effect the binding? If anyone could let me know id be grateful. thanks

self.label_var = StringVar()
self.label = CTkLabel(
    master=self.frame,
    width=label_width,
    height=height,
    fg_color=background,
    text_color=label_colour,
    textvariable=self.label_var,
)
self.label.bind("<Button-1>", lambda e: print(e))

The full class is as below. The idea was to wrap all the boiler-plate code together but also to allow me to have the label at either side of the switch.

class LabelledSwitch:
    def __init__(
        self,
        frame: CTkFrame,
        row: int,
        column: int,
        padx: Tuple[int, int],
        pady: Tuple[int, int],
        width: int,
        height: int,
        background: str,
        label_width: int,
        label_colour: str,
        label_align: str,
        label_left: bool,
        switch_width: int,
        align: str,
        callback,
    ):

        self.frame = CTkFrame(
            frame, width=width, height=height, bg_color=background, fg_color=None
        )
        self.frame.grid(row=row, column=column, padx=0, pady=0)

        self.frame.grid_rowconfigure(index=0, weight=1)
        self.frame.grid_columnconfigure(index=0, weight=0)
        self.frame.grid_columnconfigure(index=1, weight=1)

        if align == "LEFT":
            self.frame.grid(sticky="w")
        if align == "RIGHT":
            self.frame.grid(sticky="e")
        if align == "CENTER":
            self.frame.grid(sticky="")
        if align == "STRETCH":
            self.frame.grid(sticky="we")

        self.label_var = StringVar()
        self.label = CTkLabel(
            master=self.frame,
            width=label_width,
            height=height,
            fg_color=background,
            text_color=label_colour,
            textvariable=self.label_var,
        )
        self.label.bind("<Button-1>", lambda e: print(e))

        if label_left:
            self.label.grid(
                row=0,
                column=0,
                padx=(padx[0], 0),
                pady=(pady[0], pady[1]),
            )
        else:
            self.label.grid(
                row=0,
                column=1,
                padx=(5, padx[1]),
                pady=(pady[0], pady[1]),
            )
        if label_align == "LEFT":
            self.label.configure(anchor="w")
        if label_align == "RIGHT":
            self.label.configure(anchor="e")
        if label_align == "CENTER":
            self.label.configure(anchor="we")
        if label_align == "STRETCH":
            self.label.configure(anchor="we")

        self.switch_var = StringVar()
        self.switch = CTkSwitch(
            master=self.frame,
            width=switch_width,
            height=height,
            background="GREEN",
            bg_color=background,
            text="",
            variable=self.switch_var,
            onvalue="on",
            offvalue="off",
            command=callback,
        )

        if label_left:
            self.switch.grid(
                row=0,
                column=1,
                padx=(5, padx[1]),
                pady=(pady[0], pady[1]),
            )
        else:
            self.switch.grid(
                row=0,
                column=0,
                padx=(padx[0], 0),
                pady=(pady[0], pady[1]),
            )

        if align == "LEFT":
            self.switch.grid(sticky="w")
        if align == "RIGHT":
            self.switch.grid(sticky="e")
        if align == "CENTER":
            self.switch.grid(sticky="we")
        if align == "STRETCH":
            self.switch.grid(sticky="we")

CodePudding user response:

This appears to be a limitation of the CTkLabel widget. When you click on the widget, you actually click on a label embedded on the widget. Since your binding isn't on that internal embedded label, your binding won't trigger.

You can see this by printing out the value of self.label, and then adding this binding:

root.bind_all("<1>", lambda event: print(event.widget))

The output will show that self.label is named something like .!root.!frame.!ctklabel, but the widget that receives the click is something like .!root.!frame.!ctklabel.!label

You should probably file a bug with the customtkinter project.

As a workaround, you can bind to all of the inner child widgets of the label like so:

for child in self.label.winfo_children():
    child.bind("<Button-1>", lambda e: print(e))
  • Related