Widget basics

Everything you put on screen is a widget — buttons, labels, entries, frames, and so on. They all share the same small model, described here once; the widget reference pages then list only what's specific to each.

Creating widgets

Create a widget as a child of a container, using the container's factory method:

const frame = app.Frame(); // a frame inside the main window
const btn = frame.Button({ text: 'OK' }); // a button inside that frame

The global app is the main window, and it's a container — so the usual starting point is app.Something({…}).

Prefer the factory form (parent.Widget({…})). It parents the widget correctly and keeps it alive as long as its parent lives. You can write new Button({…}), but then you must keep a reference to it yourself — a widget with no references can be garbage-collected and vanish from the window.

Options are live properties

Every option you can pass to the constructor is also a property you can read and write at any time:

const e = app.Entry({ width: 30 }); // set at creation
e.width = 40; // change later
console.log(e.width); // read

Writing a property updates the widget immediately.

Raw options — .cget / .configure

The camelCase properties cover every option ScriptWeaver surfaces for a widget. For the long tail — an option with no property (a classic widget's -background, a seldom-used Tk option) — read it with .cget(name) and write it with .configure(…):

w.cget('relief'); // read any option (the leading '-' is optional) -> string
w.configure('background', '#1e1e1e'); // write one
w.configure({ relief: 'sunken', borderwidth: 2 }); // or several at once

Prefer the typed property (w.relief = 'sunken') where one exists; reach for .configure only for what they don't cover. (There is deliberately no .set(…) — that name is the value-setter on scales, scrollbars and spinboxes.)

Common methods

Every widget inherits these:

Member What it does
.pack / .grid / .place Geometry-manager proxies, e.g. w.pack.configure({ fill: 'x' }). See Layout.
.bind(seq, handler) Handle an event, e.g. w.bind('<Double-1>', …). See Events.
.tooltip(text) Show a hover tooltip; .tooltip('') clears it. See Tooltips.
.focus() Give the widget keyboard focus.
.destroy() Remove the widget (and its children).
.cget(opt) / .configure(…) Read / write any option by its raw Tk name (see below).
.winfo Geometry & tree queries: w.winfo.width(), .reqwidth(), .class(), .children(), .parent(), … (see below).
.wm Window-manager ops — title, geometry, … Meaningful on the main window and TopLevel windows: app.wm.title('My App').

Inspecting widgets — .winfo and app.byId

.winfo answers questions about a realized widget — its size, position, class, and place in the tree:

w.winfo.width(); // current size, in pixels
w.winfo.reqwidth(); // requested (natural) size
w.winfo.class(); // 'TButton', 'Frame', …
w.winfo.ismapped(); // is it on screen yet?
w.winfo.children(); // child widgets, as wrappers
w.winfo.parent(); // parent widget, as a wrapper

Sizes read 0 until the widget is mapped; if you need a measurement right after a change, flush pending layout first with app.update({ idle: true }).

When you hold only a Tk path string — from winfo.children(), a tree row, or generated code — turn it back into a usable widget with app.byId(path). It returns the widget (or null if the path isn't a live widget), after which .cget / .configure / .winfo / .destroy() all work on it.

Tooltips

Any widget can carry a hover tooltip — handy for toolbar/icon buttons:

app.Button({ text: 'Save' }).tooltip('Save the current file (Ctrl+S)');

Pass an empty string to remove it (w.tooltip('')). Tooltips are themed automatically — they follow app.setTheme() like the rest of the UI.

Global behaviour lives on sw.tooltip:

Call Effect
sw.tooltip.delay(ms) Hover delay before a tooltip shows (no argument reads the current value).
sw.tooltip.enable() / .disable() Turn all tooltips on or off.
sw.tooltip.clear(pattern?) Remove tooltips (all, or those matching a widget-path pattern).
sw.tooltip.configure({ background, foreground, font }) Override the balloon style.
sw.tooltip.fade(bool) Fade the balloon in/out where supported.

The underlying package can also target an individual menu entry, list/tree row, or notebook tab; reach those via __native_tcl('tooltip', …).

Containers vs. leaf widgets

Some widgets are containers: the main window (app), Frame, Notebook tabs, PanedWindow, and others. A container exposes a factory method for each widget type, so you build a tree by nesting:

const card = app.Frame({ padding: 10 });
card.Label({ text: 'Title' }).pack.configure();
card.Button({ text: 'Go' }).pack.configure();
card.pack.configure({ fill: 'x' });

Leaf widgets — a button, an entry, a label — hold no children.

Reactive variables

For two-way binding — keeping a value and one or more widgets in sync — use a variable (StringVar, IntVar, BoolVar, DoubleVar) together with a widget's textVariable or variable option. See Variables & reactivity.

Next