-
-
Notifications
You must be signed in to change notification settings - Fork 0
Console
One panel for every log line — preview process output, editor
logging.*calls, uncaught tracebacks. Searchable, filterable, color-coded by severity.

| Form | How | Notes |
|---|---|---|
| Docked panel |
F12 or View → Console
|
Bottom of the workspace. Default home for the log. |
| Floating window | View → Console (floating) | Pop-out for a second monitor. |
Both forms share one buffer — open one mid-run and it replays everything captured so far. Both can be open at once and stay in sync.
| Source | Captures | Notes |
|---|---|---|
| Preview subprocess |
print(), logging.*, tracebacks |
Requires Settings → Preview console mode = In-app |
| Editor (CTkMaker itself) |
logging.* at any level |
Auto-installed handler on the root logger |
| Editor | Uncaught Tk callback exceptions + log_error()
|
Same path as logging.*
|
Editor print()
|
Not captured | Use logging.info(...) instead — see Event Handlers
|
The preview's logging is pre-configured by the in-app runner — every level flows out as LEVEL | logger.name | message. You don't need logging.basicConfig() in your behavior file.
| Element | Action |
|---|---|
| Copy | Copy selection (or whole buffer when nothing selected) |
Search / Ctrl+F
|
Slide-in find bar; live highlight; Enter cycles |
| Info / Warn / Error / Debug | Severity filter checkboxes — instant elide, no rebuild |
N badge |
Live counter next to Info / Warn / Error — shows full count even when the filter hides the lines |
| Clear | Wipe buffer + counters (both editor and preview sides) |
| Stop | Terminate every running preview process |
| Auto-clear on preview | Wipe preview lines on each preview start — editor lines survive |
| Lock scroll | Stop auto-scrolling on new output; auto-toggles when you scroll up |
| × (docked only) | Close the docked panel |
| Level | Visual |
|---|---|
| DEBUG | Dim gray |
| INFO | Default foreground |
| WARNING | Amber |
| ERROR | Red |
| CRITICAL | Bold red |
Plain stderr lines (no recognized level prefix) inherit the ERROR color but do not increment the error counter — otherwise a multi-line traceback would inflate the badge unrealistically.
[14:32:01.74] [E] LEVEL | logger.name | message
| Part | Meaning |
|---|---|
[14:32:01.74] |
Centisecond timestamp. Omitted on continuation lines (see below). |
[E] |
Editor-source marker. Preview lines omit it. |
LEVEL | logger.name | message |
Standard logging format — parsed for the level color. |
When two stdout / stderr lines arrive within 500 ms on the same stream (typical multi-line traceback), the second one drops its [ts] prefix. Event boundaries become visually obvious — you see where one error ends and the next begins.
Explicit logging.* calls always show their own timestamp regardless — they're discrete events.
Hard cap at 10 000 characters per line. Longer content renders as:
… first 10 000 chars … [truncated, +N chars]
The full text stays in the buffer for future expand support.

| Item | Action |
|---|---|
| Copy | Same as toolbar |
| Select all | Select the whole buffer |
| Clear | Same as toolbar |
| Emit colour test palette | Inject one line at each severity — quick visual check for your theme |
- Preview lines — 5 000 entries, FIFO eviction
- Editor lines — 1 000 entries, protected from preview-flood eviction
A chatty preview cannot push an editor warning out of the buffer.
Several ways to surface what your code is doing, from least to most structured. Put any of these inside your Event Handlers and run Preview — output lands in the Console.
def on_score_change(self):
print(f"score = {self.score}")Works inside a preview run; output renders with the default stdout style. Doesn't show in editor code — use logging for that.
import logging
log = logging.getLogger("game")
def on_button_click(self):
log.debug("clicked at frame %d", self.frame)
log.info("score: %s", self.score)
log.warning("low health: %d", self.health)
log.error("failed to load %s", path)
log.critical("save file corrupted")Each level renders in its own color (see the severity table above). The first arg is the format string; remaining args fill in lazily — cheaper than f-strings when DEBUG is hidden by the filter.
def on_load_clicked(self):
try:
self._load_save_file()
except OSError:
log.exception("save file load failed")log.exception(...) is log.error(...) plus the full traceback, automatic — use it inside an except clause.
def update_health(self, value):
assert 0 <= value <= 100, f"health out of range: {value}"
self.health = valueA failing assert raises AssertionError, which the Tk callback handler routes to the Console with a red traceback — same path as any other unhandled exception.
Drop a one-line log.debug(...) instead of reaching for a breakpoint — fast iteration during a preview loop:
def step_physics(self):
self.vx += self.ax
log.debug("vx after gravity: %.2f", self.vx)
self.x += self.vxThe Debug filter is off by default — enable it on the toolbar to see these lines.
log = logging.getLogger(f"page.{__name__}")
# or per subsystem
physics_log = logging.getLogger("game.physics")
ui_log = logging.getLogger("game.ui")Lines render as INFO | game.physics | … — search the Console (Ctrl+F) by logger name to isolate one subsystem when several are chatty.
-
print()in CTkMaker app code doesn't show. Only preview-processprint()is captured. Uselogging.info(...)for editor-side debug output — see Event Handlers. - Counter shows N, but no lines visible. A filter is hiding the level. Check the Info / Warn / Error / Debug boxes.
-
Third-party noise (PIL, urllib3, matplotlib, asyncio) is muted to
WARNINGby default. Re-enable per logger withlogging.getLogger("PIL").setLevel(logging.DEBUG)if you need to debug image decoding. -
Preview output goes elsewhere. Settings → Preview console mode picks between In-app (capture here), Windows console (separate
cmdwindow), and Off (discarded).
See also — Preview · Event Handlers · Settings · Keyboard Shortcuts