-
-
Notifications
You must be signed in to change notification settings - Fork 0
Event Handlers
Bind widget events (click, change, key press…) to Python methods. Each window owns its own behavior file; CTkMaker writes the stub, you write the body.
Every window keeps its handlers in its own Python file:
<project>/assets/scripts/<page>/<window>.py
Inside is one class — <WindowSlug>Page — with a setup(self, window) method and one method per bound handler. The exporter imports this class and wires it into the generated UI automatically.
The file is created lazily on the first handler attach (or eagerly when a new window is added).
Two paths — both end up at the same place.
Canvas right-click → Add handler ▸
Cascade lists every event the widget supports (command, <Return>, <FocusOut>, …). Pick one → CTkMaker generates a method name, appends a stub, and opens your editor at the new line.
Properties panel → Events group
The Events group lands at the end of the widget's schema. The header shows [+] to add an action; bound rows show the method name + docstring and an [✕] to unbind. Hover any event header to see a one-line description of when it fires plus any caveat.
Widgets with many bind events (CTkLabel for example) split their event list:
- Default — the small set of events you usually want (click, hover, value change).
-
Advanced — collapsible sub-group for rare events, high-frequency events, or events with a precondition. CTkMaker tags these with a warning so you don't bind them by accident:
-
<Motion>,<Configure>— fire at 60+ Hz; keep the handler cheap. -
<FocusIn>,<FocusOut>,<KeyPress>,<KeyRelease>— requiretakefocus=Trueon the widget; nothing fires otherwise.
-
The same partition shows up in the canvas right-click cascade as a nested Advanced ▸ submenu.
| Action | How |
|---|---|
| Add |
[+] on event header, or right-click → Add action
|
| Open in editor | Double-click row, F7, or right-click → Open in editor
|
| Reorder | Right-click row → Move up / Move down |
| Unbind |
[✕] on row, or right-click → Unbind
|
One event can run several methods in order. The exporter chains them as a lambda: (m1(), m2(), m3()) for command= events, or as separate bind(seq, fn, add="+") calls for bind-style events. Reordering rows in the Events group changes the call order.
F7 (or any "Open in editor" entry) launches your editor at the right line.
Configure in Settings → Editor:
| Preset | Notes |
|---|---|
| Auto | VS Code → Notepad++ → IDLE fallback chain |
| VS Code | Recommended; opens project folder + jumps to line |
| Notepad++ | Lightweight |
| IDLE | Always available — runs python -m idlelib
|
| Custom | Free-form command with {file}, {line}, {folder}, {python} placeholders |
A widget with at least one bound handler shows a ▶ glyph after its name in the Object Tree.
-
Rename a window — the
.pyfile and class header are renamed in lockstep. Comments and bodies stay intact. -
Delete a window — a dialog surfaces widget / variable / script-line counts and offers two paths for the
.py:- Delete → routes the file to the OS recycle bin
-
Save copy → moves it to
<project>/assets/scripts_archive/<page>/
Action delete works the same: a confirmation dialog (Cancel / Open in editor / Delete) before the method is removed from the file. Blank lines and comments around the method are preserved.
Ctrl+R (Preview) runs the project in a separate console window so any print() from your handler stays visible alongside the UI.
On export, every window with handlers gets:
from assets.scripts.<page>.<window> import <Class>Page
…
self._behavior = <Class>Page()
self._behavior.setup(self)…and each event becomes a command=self._behavior.method_name (or a bind(...) call after __init__).
See also — Properties Panel · Variables · Settings · Exporting Code