Skip to content

CTkLabel with takefocus=True needs 2 Tab presses per move — focus stops on inner CTkCanvas #2803

@kandelucky

Description

@kandelucky

When two CTkLabels share a parent and both have takefocus=True, Tab traversal doesn't go directly from one to the other — it makes an invisible stop on each label's internal CTkCanvas. So two Tab presses are needed for one visible move.

Reproduction

import customtkinter as ctk

def log(name):
return lambda e: print(f"[{name}] type={e.type} widget={str(e.widget).split('.')[-1]}")

root = ctk.CTk()
root.geometry("420x180")

a = ctk.CTkLabel(root, text="a", takefocus=True, fg_color=("#ddd", "#303030"),
width=240, height=36, corner_radius=6)
b = ctk.CTkLabel(root, text="b", takefocus=True, fg_color=("#ddd", "#303030"),
width=240, height=36, corner_radius=6)
a.pack(pady=6); b.pack(pady=6)

for w, n in ((a, "a"), (b, "b")):
w.bind("", log(n))
w.bind("", log(n))

root.after(200, a.focus_set)
root.mainloop()
Click the window, press Tab.

Actual

[a] type=10 widget=!label ← FocusOut from a
[b] type=9 widget=!ctkcanvas ← intermediate stop on canvas (Tab #1)
[b] type=10 widget=!ctkcanvas
[b] type=9 widget=!label ← finally on b (Tab #2)
Expected

[a] type=10 widget=!label
[b] type=9 widget=!label ← single press, single move
Cause
CTkLabel._canvas is a tkinter.Canvas subclass. Canvas's default takefocus="" defers to Tk's heuristic, which includes widgets with class-level key bindings — and Canvas does. So traversal walks through it before reaching the inner tk.Label.

Suggested fix
In customtkinter/windows/widgets/ctk_label.py, pass takefocus=0 to self._canvas at construction. Same pattern likely affects other composite widgets (CTkButton, CTkEntry, ...) — worth a sweep.

Workaround

label._canvas.configure(takefocus=0)
Note
Hit this while working on my own project — CTkMaker, a drag-and-drop designer for CustomTkinter. Patched locally with the workaround above; filing here so it can be fixed at the source.

ctk_label_focus_fixed.py
ctk_label_focus_buggy.py

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions