Skip to content

Reference

Window

Bases: _LayoutMixin, _WindowBaseClass

Basic Window class from which all windows are derived

Notes

Classes which inherit from window should implement handle_event, setup, and teardown as needed

Source code in guitk/window.py
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
class Window(_LayoutMixin, _WindowBaseClass):
    """Basic Window class from which all windows are derived

    Notes:
        Classes which inherit from window should implement handle_event, setup, and teardown as needed
    """

    def __init__(
        self,
        parent: tk.Tk | None = None,
        title: str | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        topmost: bool | None = None,
        autoframe: bool = False,
        theme: str | None = None,
        tooltip: TooltipType | None = None,
        modal: bool | None = None,
        size: SizeType = None,
    ):
        # call _config then subclass's config to initialize
        # layout, title, menu, etc.

        self.autoframe = autoframe

        self._config()
        self.config()

        # override any layout defaults from constructor
        self.title: str | None = title if title is not None else self.title
        self.padx: int | None = padx if padx is not None else self.padx
        self.pady: int | None = pady if pady is not None else self.pady
        self.theme: str | None = theme if theme is not None else self.theme
        self.tooltip: TooltipType | None = (
            tooltip if tooltip is not None else self.tooltip
        )
        self.modal: bool | None = modal if modal is not None else self.modal
        self.size: SizeType = size if size is not None else self.size

        self._id: int = id(self)
        self._tk: _TKRoot = _TKRoot()
        self._parent = parent or self._tk.root
        self._topmost = topmost

        self.window: tk.TopLevel = tk.Toplevel(self._parent)
        self.window.title(self.title)
        self._widgets = []
        self._widget_by_key = {}

        self._timer_events = {}
        """ timer events that have been set by bind_timer_event, stores most recent after() id for event"""

        self._timer_events_cancelled = {}
        """ timer events that have been set by bind_timer_event but then cancelled """

        self._return_value = None
        """ value returned from run() if set in quit() """

        self._root_menu = None
        """ will hold root tk.Menu widget"""

        self._radiobuttons = {}
        """ will hold group name/variable for radio buttons in the window """

        self._destroyed = False
        """ set to True when window is destroyed """

        self._mainframe = ttk.Frame(self.window, padding="3 3 12 12")
        self._mainframe.grid(column=0, row=0, sticky="nsew")
        self.window.columnconfigure(0, weight=1)
        self.window.rowconfigure(0, weight=1)

        self._tk.register(self)
        self.window.protocol(
            "WM_DELETE_WINDOW",
            self._make_callback(Event(self, self, EventType.Quit, EventType.Quit)),
        )

        if not self.layout:
            self.layout = [
                [
                    Label(
                        "Looks like you forgot to include a layout in your class definition"
                    )
                ]
            ]

        self._commands = []

        self._layout(self._mainframe, self)

        # apply theme if necessary
        if self.theme is not None:
            self._tk.theme = self.theme

        self._grid_configure_widgets()

        if self.menu:
            self._build_menu()

        if self._topmost or self.modal:
            self.window.attributes("-topmost", 1)

        if self.modal:
            windowingsystem = self.root.call("tk", "windowingsystem")
            if windowingsystem == "aqua":
                with contextlib.suppress(Exception):
                    self.root.call(
                        "::tk::unsupported::MacWindowStyle",
                        "style",
                        self._w,
                        "moveableModal",
                        "",
                    )
            if self._parent is not None and self._parent.winfo_viewable():
                self.window.transient(self._parent)
            self.window.wait_visibility()
            self.window.grab_set()

        if self.size is not None:
            size = (
                self.size
                if isinstance(self.size, str)
                else f"{self.size[0]}x{self.size[1]}"
            )
            self.window.geometry(size)

        # TODO: add geometry code to ensure window appears in good spot relative to parent

        # setup event handling
        self.events = True
        self._bind_timer_event(
            100, EventType.WindowFinishedLoading.value, EventType.WindowFinishedLoading
        )
        self._bind_event_handlers()
        self._create_setup_teardown_events()

        self.setup()
        self.root.event_generate(EventType.Setup.value)

        if self.modal:
            self.window.wait_window()

    def _grid_configure_widgets(self):
        """Apply padding to all widgets in the window"""
        # apply padding, widget padding takes precedent over window
        for widget in self._widgets:
            padx = widget.padx if widget.padx is not None else self.padx
            pady = widget.pady if widget.pady is not None else self.pady
            widget.widget.grid_configure(padx=padx, pady=pady)

    def _config(self):
        self.title = "My Window"
        """Title to display in the window's title bar """

        self.layout = []
        """Every class that inherits from Window must define it's own layout """

        self.menu: MenuBar | None = None
        """ Optionally provide a menu """

        self.padx = DEFAULT_PADX
        self.pady = DEFAULT_PADY
        """Default padding around widgets """

        self.theme = None
        """The ttk theme to use, if None, uses ttk default"""

        self.tooltip = None
        """ A callable which returns the tooltip text for a given key or a str """

        self.modal = False
        """ Set to True to create modal window """

        self.size = None
        """ Set to a tuple of (width, height) to set the window size """

        push_parent(self)

    def config(self):
        pass

    def handle_event(self, event: Event):
        """Handle event objects, inheriting classes should implement handle_event"""
        ...
        # if event.event_type == EventType.Quit:
        # self.quit(self._return_value)

    def setup(self):
        """Perform any needed setup for the window.
        Gets called immediately after __init__
        """
        pass

    def teardown(self):
        """Perform any cleanup before the window closes.
        Gets called immediately before the window is destroyed
        """
        pass

    @debug_watch
    def quit(self, return_value: Any = None):
        """Called when closing the window"""
        # set return value which is returned by run()
        self._return_value = return_value
        self._destroy()

    @property
    def title(self):
        return self._title

    @title.setter
    def title(self, value):
        self._title = value

    @property
    def geometry(self):
        return self.size

    @geometry.setter
    def geometry(self, value):
        self.size = value

    def bind_command(self, key=None, event_type=None, command=None):
        if not any([key, event_type]):
            raise ValueError("At least one of key, event_type must be specified")
        self._bind_command(
            EventCommand(widget=None, key=key, event_type=event_type, command=command)
        )

    def _bind_command(self, event_command: EventCommand):
        self._commands.append(event_command)

    def bind_timer_event(self, delay, event_name, repeat=False, command=None):
        """Create a new virtual event `event_name` that fires after `delay` ms,
        repeats every `delay` ms if repeat=True, otherwise fires once"""
        if command:
            self.bind_command(
                key=event_name, event_type=EventType.VirtualEvent, command=command
            )
        return self._bind_timer_event(delay, event_name, EventType.VirtualEvent, repeat)

    def _bind_timer_event(self, delay, event_name, event_type, repeat=False):
        # create a unique name for the timer
        timer_id = f"{event_name}_{time.time_ns()}"

        # callback that generates event and respawns the timer if repeat=True
        # when cancelling with cancel_timer_event, sometimes the call to after_cancel doesn't apparently work so check
        # if timer_id is in _timer_events_cancelled before respawning
        def _generate_event():
            self.root.event_generate(event_name)
            if repeat and timer_id not in self._timer_events_cancelled:
                self._timer_events[timer_id] = self._tk.root.after(
                    delay, _generate_event
                )

        event = Event(self, self, event_name, event_type)
        self.root.bind(event_name, self._make_callback(event))
        self._timer_events[timer_id] = self._tk.root.after(delay, _generate_event)
        return timer_id

    def _create_setup_teardown_events(self):
        """Create the setup and teardown events"""
        setup_event = Event(self, self, EventType.Setup.value, EventType.Setup)
        self.root.bind(EventType.Setup.value, self._make_callback(setup_event))

        teardown_event = Event(self, self, EventType.Teardown.value, EventType.Teardown)
        self.root.bind(EventType.Teardown.value, self._make_callback(teardown_event))

    def cancel_timer_event(self, timer_id):
        """Cancel a timer event created with bind_timer_event"""
        try:
            after_id = self._timer_events[timer_id]
            self.root.after_cancel(after_id)
            self._timer_events.pop(timer_id)
            self._timer_events_cancelled[timer_id] = after_id
        except KeyError as e:
            raise ValueError(f"Timer event {timer_id} not found") from e
        except Exception as e:
            raise e

    def _bind_event_handlers(self):
        """Bind any event handlers decorated with @on"""
        for method in self.__class__.__dict__.values():
            if hasattr(method, "_guitk_event_handlers"):
                for key, event_type in getattr(method, "_guitk_event_handlers"):
                    self.bind_command(key=key, event_type=event_type, command=method)

    def add_widget(self, widget: BaseWidget, row: int, col: int):
        """Add a widget to the window's mainframe"""
        widget._create_widget(self._mainframe, self, row, col)
        self._widgets.append(widget)
        self._widget_by_key[widget.key] = widget
        self._grid_configure_widgets()

    def remove(self, key_or_widget: Hashable | BaseWidget):
        """Remove widget from window and destroy it."""
        for idx, widget in enumerate(self._widgets):
            debug(f"{idx=} {widget=} {key_or_widget=}")
            if widget == key_or_widget or widget.key == key_or_widget:
                widget = self._widgets[idx]
                if widget.parent == self:
                    self._remove(widget)
                else:
                    widget.parent.remove(widget)
                return
        raise ValueError(f"Widget {key_or_widget} not found in Window")

    def _remove(self, widget: BaseWidget):
        """Remove widget from window and destroy it."""
        widget.widget.grid_forget()
        widget.widget.destroy()
        self._widget_by_key.pop(widget.key, None)
        self._widgets.remove(widget)
        self.window.update_idletasks()

    def _insert_widget_row_col(self, widget: BaseWidget, row: int, col: int):
        """Insert a widget into the window's mainframe after the container has been created
            Intended for use at run-time only when widgets need to be added dynamically

        Args:
            widget: (Widget) the widget to add
            row: (int) the row to insert the widget into
            col: (int) the column to insert the widget into

        Note:
            This method is included in Window so that Widget.replace() works properly for
            widgets added directly to a layout. It does not expand the layout like the similar
            method in _Container.
        """
        # TODO: fix this so it actually inserts instead of replaces
        self.add_widget(widget, row, col)

    def run(self):
        self._tk.run_mainloop()
        return self._return_value

    @property
    def root(self):
        """Return Tk root instance"""
        return self._tk.root

    @property
    def widgets(self) -> list[BaseWidget]:
        """ "Return list of all widgets belonging to the window"""
        return self._widgets

    def children(self):
        """Return child windows"""
        return self._tk.get_children(self)

    def get(self, key: Hashable) -> BaseWidget:
        """Get widget with key or raise KeyError if not found"""
        try:
            return self._widget_by_key[key]
        except KeyError as e:
            raise KeyError(f"Widget with key {key} not found") from e

    def _add_widget(self, widget: BaseWidget):
        """Dummy method to allow widgets to be added with VLayout()/HLayout()"""
        pass

    def _forget_widget(self, widget: BaseWidget):
        """Remove widget from the window's bookkeeping but don't destroy it"""
        self._widget_by_key.pop(widget.key, None)
        self._widgets.remove(widget)

    def _add_menus(self, menu: Menu, path: str | None = None):
        """Add menus to the window recursively

        Args:
            menu (Menu): the Menu object to add
            path (str, optional): the path to the menu item which is used as the key
        """
        path = f"{MENU_MARKER}{menu._label}" if path is None else path
        for m in menu:
            subpath = f"{path}|{m._label}"
            m._create_widget(menu._menu, self, subpath)
            self._widgets.append(m)
            self._widget_by_key[m.key] = m
            if isinstance(m, Menu):
                self._add_menus(m, subpath)

    def _build_menu(self):
        """Build the menu bar"""
        if self._root_menu is None:
            # create the root menu
            self.root.option_add("*tearOff", tk.FALSE)
            self._root_menu = tk.Menu(self.root)
            self.window["menu"] = self._root_menu

        for m in self.menu:
            if not isinstance(m, Menu):
                raise ValueError("self.menu items must be Menu objects")
            path = f"{MENU_MARKER}{m._label}"
            m._create_widget(self._root_menu, self, path)
            self._widgets.append(m)
            self._widget_by_key[m.key] = m
            self._add_menus(m, path)

    @debug_watch
    def _destroy(self):
        """Destroy the window and all child windows and perform cleanup"""
        if self._destroyed:
            # HACK: avoid multiple calls to _destroy which can occur if
            # the user handles the Quit event themselves
            # TODO: find a better way to handle this
            return

        # call teardown to perform any cleanup
        self.teardown()

        # generate a Teardown event
        self.root.event_generate(EventType.Teardown.value)

        # kill any child windows
        for child in self.children():
            event = Event(child, child.window, EventType.Quit, EventType.Quit)
            child.handle_event(event)
            with contextlib.suppress(Exception):
                child._destroy()

        # disable event processing in _handle_event
        self.events = False

        # disable any stdout/stderr redirection and event handling
        for widget in self._widgets:
            widget.events = False

            if "guitk.widgets.tk_text.Output" in str(type(widget)):
                widget.disable_redirect()

        if self.modal:
            self.window.grab_release()

        # cancel any timer events
        for timer_id in self._timer_events:
            with contextlib.suppress(Exception):
                after_id = self._timer_events[timer_id]
                self._tk.root.after_cancel(after_id)
        self._parent.focus_set()
        self.window.destroy()
        self._tk.deregister(self)
        self._destroyed = True

    def _make_callback(self, event):
        def _callback(*arg):
            if arg:
                event.event = arg[0]
            self._handle_event(event)

        return _callback

    @debug_watch
    def _handle_event(self, event: Event):
        """Handle events for this window"""
        # only handle events if widget has events=True; Window objects always get events
        if isinstance(event.widget, (BaseWidget, Window)) and not event.widget.events:
            return

        # filter events for this window
        if event.id != self._id:
            return

        # swallow MenuCommand events if the menu is disabled
        # if event.event_type == EventType.MenuCommand and not self.menu.enabled:

        # handle custom commands
        self._handle_commands(event)

        # call subclass handle_event
        self.handle_event(event)

        # if deleting the window, call _destroy after handle_event has had a chance to handle it
        if event.event_type == EventType.Quit:
            self._destroy()

    @debug_watch
    def _handle_commands(self, event):
        """Handle commands bound to widgets in the window"""
        for command in self._commands:
            if (
                (command.widget is None or command.widget == event.widget)
                and (command.key is None or command.key == event.key)
                and (
                    command.event_type is None or command.event_type == event.event_type
                )
            ) or command.event_type == EventType.Any:
                if hasattr(command.command, "_guitk_event_handlers"):
                    # command was decorated with @on, so it's a method of this class
                    if len(inspect.signature(command.command).parameters) == 2:
                        # command has a second argument, assume it's the event
                        command.command(self, event)
                    else:
                        command.command(self)
                else:
                    command.command()

    def __getitem__(self, key) -> BaseWidget:
        try:
            return self._widget_by_key[key]
        except KeyError as e:
            raise KeyError(f"Invalid key: no widget with key {key}") from e

root property

Return Tk root instance

widgets: list[BaseWidget] property

"Return list of all widgets belonging to the window

add_widget(widget, row, col)

Add a widget to the window's mainframe

Source code in guitk/window.py
318
319
320
321
322
323
def add_widget(self, widget: BaseWidget, row: int, col: int):
    """Add a widget to the window's mainframe"""
    widget._create_widget(self._mainframe, self, row, col)
    self._widgets.append(widget)
    self._widget_by_key[widget.key] = widget
    self._grid_configure_widgets()

bind_timer_event(delay, event_name, repeat=False, command=None)

Create a new virtual event event_name that fires after delay ms, repeats every delay ms if repeat=True, otherwise fires once

Source code in guitk/window.py
263
264
265
266
267
268
269
270
def bind_timer_event(self, delay, event_name, repeat=False, command=None):
    """Create a new virtual event `event_name` that fires after `delay` ms,
    repeats every `delay` ms if repeat=True, otherwise fires once"""
    if command:
        self.bind_command(
            key=event_name, event_type=EventType.VirtualEvent, command=command
        )
    return self._bind_timer_event(delay, event_name, EventType.VirtualEvent, repeat)

cancel_timer_event(timer_id)

Cancel a timer event created with bind_timer_event

Source code in guitk/window.py
299
300
301
302
303
304
305
306
307
308
309
def cancel_timer_event(self, timer_id):
    """Cancel a timer event created with bind_timer_event"""
    try:
        after_id = self._timer_events[timer_id]
        self.root.after_cancel(after_id)
        self._timer_events.pop(timer_id)
        self._timer_events_cancelled[timer_id] = after_id
    except KeyError as e:
        raise ValueError(f"Timer event {timer_id} not found") from e
    except Exception as e:
        raise e

children()

Return child windows

Source code in guitk/window.py
377
378
379
def children(self):
    """Return child windows"""
    return self._tk.get_children(self)

get(key)

Get widget with key or raise KeyError if not found

Source code in guitk/window.py
381
382
383
384
385
386
def get(self, key: Hashable) -> BaseWidget:
    """Get widget with key or raise KeyError if not found"""
    try:
        return self._widget_by_key[key]
    except KeyError as e:
        raise KeyError(f"Widget with key {key} not found") from e

handle_event(event)

Handle event objects, inheriting classes should implement handle_event

Source code in guitk/window.py
212
213
214
def handle_event(self, event: Event):
    """Handle event objects, inheriting classes should implement handle_event"""
    ...

quit(return_value=None)

Called when closing the window

Source code in guitk/window.py
230
231
232
233
234
235
@debug_watch
def quit(self, return_value: Any = None):
    """Called when closing the window"""
    # set return value which is returned by run()
    self._return_value = return_value
    self._destroy()

remove(key_or_widget)

Remove widget from window and destroy it.

Source code in guitk/window.py
325
326
327
328
329
330
331
332
333
334
335
336
def remove(self, key_or_widget: Hashable | BaseWidget):
    """Remove widget from window and destroy it."""
    for idx, widget in enumerate(self._widgets):
        debug(f"{idx=} {widget=} {key_or_widget=}")
        if widget == key_or_widget or widget.key == key_or_widget:
            widget = self._widgets[idx]
            if widget.parent == self:
                self._remove(widget)
            else:
                widget.parent.remove(widget)
            return
    raise ValueError(f"Widget {key_or_widget} not found in Window")

setup()

Perform any needed setup for the window. Gets called immediately after init

Source code in guitk/window.py
218
219
220
221
222
def setup(self):
    """Perform any needed setup for the window.
    Gets called immediately after __init__
    """
    pass

teardown()

Perform any cleanup before the window closes. Gets called immediately before the window is destroyed

Source code in guitk/window.py
224
225
226
227
228
def teardown(self):
    """Perform any cleanup before the window closes.
    Gets called immediately before the window is destroyed
    """
    pass

HLayout

A Layout manager that aligns widgets horizontally

Source code in guitk/layout.py
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
class HLayout:
    """A Layout manager that aligns widgets horizontally"""

    def __init__(
        self,
        layout: LayoutType = None,
        *,
        valign: VAlign | None = None,
        halign: HAlign | None = None,
    ):
        self._layout_list = layout or []
        self.index = 0
        self.valign = valign
        self.halign = halign
        self.window = None

        # get the caller's instance so we can set the layout
        caller_frame = currentframe().f_back
        with contextlib.suppress(IndexError, KeyError):
            first_arg = caller_frame.f_code.co_varnames[0]
            caller_instance = caller_frame.f_locals[first_arg]
            # determine if the caller is a Window
            # need to use repr() because we can't import Window here without causing a circular import
            if "guitk.window.Window" in repr(getmro(caller_instance.__class__)):
                # HLayout is being used in a Window, so set the Window's layout automatically
                self.window = caller_instance
                self.window.layout = self

    def append(self, widget: BaseWidget):
        """Add a widget to the end of the HLayout"""
        if not self.window:
            # HLayout is not being used in a Window, can't add widget
            raise RuntimeError(
                "Layout must have been created in a Window to add widgets"
            )
        self.window.col_count += 1
        self.window.add_widget(widget, 0, self.window.col_count)

    def remove(self, key_or_widget: Hashable | BaseWidget):
        """Remove widget from layout" and destroy it.

        Args:
            key_or_widget (Hashable | Widget): The key or widget to remove. If a key is given,
                the first widget with that key will be removed.

        Raises:
            RuntimeError: If called and the layout was not created in a Window.
            ValueError: If the widget is not found in the layout.
        """
        if not self.window:
            raise RuntimeError(
                "Layout must have been created in a Window to remove widgets"
            )
        for idx, widget in enumerate(self._layout_list):
            if widget == key_or_widget or widget.key == key_or_widget:
                widget = self._layout_list.pop(idx)
                self.window._forget_widget(widget)
                widget.widget.grid_forget()
                widget.widget.destroy()
                self.window.window.update_idletasks()
                return
        raise ValueError(f"Widget {key_or_widget} not found in Layout")

    def _add_widget(self, widget):
        """Add a widget to the end of the Layout"""
        self._layout_list.append(widget)

    @property
    def layout(self) -> LayoutType:
        """Return the layout list"""
        # if layout manually created, it will be a list of lists
        # otherwise it's a row of widgets, so wrap it in a list
        return (
            self._layout_list
            if self._layout_list and isinstance(self._layout_list[0], (list, tuple))
            else [self._layout_list]
        )

    def __enter__(self):
        push_parent(self)
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        pop_parent()
        return False

    def __iter__(self):
        self.index = 0
        return iter(self.layout)

    def __next__(self):
        if self.index >= len(self.layout):
            raise StopIteration
        value = self.layout[self.index]
        self.index += 1
        return value

layout: LayoutType property

Return the layout list

append(widget)

Add a widget to the end of the HLayout

Source code in guitk/layout.py
84
85
86
87
88
89
90
91
92
def append(self, widget: BaseWidget):
    """Add a widget to the end of the HLayout"""
    if not self.window:
        # HLayout is not being used in a Window, can't add widget
        raise RuntimeError(
            "Layout must have been created in a Window to add widgets"
        )
    self.window.col_count += 1
    self.window.add_widget(widget, 0, self.window.col_count)

remove(key_or_widget)

Remove widget from layout" and destroy it.

Parameters:

Name Type Description Default
key_or_widget Hashable | Widget

The key or widget to remove. If a key is given, the first widget with that key will be removed.

required

Raises:

Type Description
RuntimeError

If called and the layout was not created in a Window.

ValueError

If the widget is not found in the layout.

Source code in guitk/layout.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def remove(self, key_or_widget: Hashable | BaseWidget):
    """Remove widget from layout" and destroy it.

    Args:
        key_or_widget (Hashable | Widget): The key or widget to remove. If a key is given,
            the first widget with that key will be removed.

    Raises:
        RuntimeError: If called and the layout was not created in a Window.
        ValueError: If the widget is not found in the layout.
    """
    if not self.window:
        raise RuntimeError(
            "Layout must have been created in a Window to remove widgets"
        )
    for idx, widget in enumerate(self._layout_list):
        if widget == key_or_widget or widget.key == key_or_widget:
            widget = self._layout_list.pop(idx)
            self.window._forget_widget(widget)
            widget.widget.grid_forget()
            widget.widget.destroy()
            self.window.window.update_idletasks()
            return
    raise ValueError(f"Widget {key_or_widget} not found in Layout")

VLayout

Bases: HLayout

A Layout manager that aligns widgets vertically

Source code in guitk/layout.py
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
class VLayout(HLayout):
    """A Layout manager that aligns widgets vertically"""

    @property
    def layout(self):
        return [[w] for w in self._layout_list]

    def append(self, widget: BaseWidget):
        """Add a widget to the bottom of the VLayout"""
        if not self.window:
            # HLayout is not being used in a Window, can't add widget
            raise RuntimeError(
                "VLayout must have been created in a Window to add widgets"
            )
        self.window.row_count += 1
        self.window.add_widget(widget, self.window.row_count, 0)

append(widget)

Add a widget to the bottom of the VLayout

Source code in guitk/layout.py
161
162
163
164
165
166
167
168
169
def append(self, widget: BaseWidget):
    """Add a widget to the bottom of the VLayout"""
    if not self.window:
        # HLayout is not being used in a Window, can't add widget
        raise RuntimeError(
            "VLayout must have been created in a Window to add widgets"
        )
    self.window.row_count += 1
    self.window.add_widget(widget, self.window.row_count, 0)

HStack

Bases: _Stack

A container that stacks widgets horizontally when added to a Layout

Source code in guitk/containers.py
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
class HStack(_Stack):
    """A container that stacks widgets horizontally when added to a Layout"""

    def __init__(
        self,
        key: Hashable | None = None,
        height: int | None = None,
        padding: PaddingType | None = None,
        disabled: bool | None = False,
        sticky: str | None = "nsew",
        valign: VAlign | None = None,
        halign: HAlign | None = None,
        vexpand: bool = True,
        hexpand: bool = True,
        distribute: bool = False,
        vspacing: PadType | None = None,
        hspacing: PadType | None = None,
        vscrollbar: bool = False,
        # hscrollbar: bool = False,
        autohide_scrollbars: bool = True,
    ):
        """A container that stacks widgets horizontally when added to a Layout

        Args:
            key (Hashable, optional): The key to use for the HStack. Defaults to None.
            height (int, optional): The height of the HStack. Defaults to None.
            padding (PaddingType, optional): The padding around the HStack. Defaults to None.
            disabled (bool, optional): Whether the HStack is disabled. Defaults to False.
            sticky (str, optional): The sticky value for the HStack. Defaults to "nsew".
            valign (VAlign, optional): The vertical alignment for the widgets in the HStack.
                Defaults to None.
            halign (HAlign, optional): The horizontal alignment for the widgets in the HStack.
                Defaults to None.
            vexpand (bool, optional): Whether the Stack should expand vertically.
                Defaults to True.
            hexpand (bool, optional): Whether the Stack should expand horizontally.
                Defaults to True.
            distribute (bool, optional): Whether the HStack should distribute widgets evenly.
            vspacing (PadType, optional): Vertical spacing between widgets. Defaults to None.
            hspacing (PadType, optional): Horizontal spacing between widgets. Defaults to None.
            vscrollbar (bool): Whether to include a vertical scrollbar. Defaults to False.
            autohide_scrollbars (bool): Whether to hide scrollbars when not needed. Defaults to True.

        Note:
            If height is specified, the HStack will not expand to fill the available space and the
            expand parameter will be ignored.
        """
        super().__init__(
            key=key,
            height=height,
            width=None,
            padding=padding,
            disabled=disabled,
            sticky=sticky,
            valign=valign,
            halign=halign,
            vexpand=vexpand,
            hexpand=hexpand,
            distribute=distribute,
            vspacing=vspacing,
            hspacing=hspacing,
            vscrollbar=vscrollbar,
            # hscrollbar=hscrollbar,
            autohide_scrollbars=autohide_scrollbars,
        )

    @property
    def layout(self) -> list[list[BaseWidget]]:
        """Return the layout of the HStack"""
        if self.distribute:
            self._layout_lol = [[]]
            for widget in self._layout_list:
                self._layout_lol[0].append(HSpacer())
                self._layout_lol[0].append(widget)
            self._layout_lol[0].append(HSpacer())
        else:
            self._layout_lol = [self._layout_list]
        return self._layout_lol

    @layout.setter
    def layout(self, layout: list[list[BaseWidget]]):
        """Set the layout of the VStack"""
        self._layout_lol = layout
        self._layout_list = [widget for row in layout for widget in row]

    @debug_watch
    def _insert_widget_row_col(
        self, widget: BaseWidget, row: int, col: int, is_vertical: bool = True
    ):
        """Insert a widget into the container after the container has been created
            Intended for use at run-time only when widgets need to be added dynamically

        Args:
            widget: (Widget) the widget to add
            row: (int) the row to insert the widget into
            col: (int) the column to insert the widget into

        Note: widgets are placed in a grid with row, col coordinates by the _LayoutMixin class.
        All containers store widgets internally as a list so we need to convert the row, col
        coordinates to a list index.
        """
        super()._insert_widget_row_col(widget, row, col, is_vertical=False)

layout: list[list[BaseWidget]] property writable

Return the layout of the HStack

__init__(key=None, height=None, padding=None, disabled=False, sticky='nsew', valign=None, halign=None, vexpand=True, hexpand=True, distribute=False, vspacing=None, hspacing=None, vscrollbar=False, autohide_scrollbars=True)

A container that stacks widgets horizontally when added to a Layout

Parameters:

Name Type Description Default
key Hashable

The key to use for the HStack. Defaults to None.

None
height int

The height of the HStack. Defaults to None.

None
padding PaddingType

The padding around the HStack. Defaults to None.

None
disabled bool

Whether the HStack is disabled. Defaults to False.

False
sticky str

The sticky value for the HStack. Defaults to "nsew".

'nsew'
valign VAlign

The vertical alignment for the widgets in the HStack. Defaults to None.

None
halign HAlign

The horizontal alignment for the widgets in the HStack. Defaults to None.

None
vexpand bool

Whether the Stack should expand vertically. Defaults to True.

True
hexpand bool

Whether the Stack should expand horizontally. Defaults to True.

True
distribute bool

Whether the HStack should distribute widgets evenly.

False
vspacing PadType

Vertical spacing between widgets. Defaults to None.

None
hspacing PadType

Horizontal spacing between widgets. Defaults to None.

None
vscrollbar bool

Whether to include a vertical scrollbar. Defaults to False.

False
autohide_scrollbars bool

Whether to hide scrollbars when not needed. Defaults to True.

True
Note

If height is specified, the HStack will not expand to fill the available space and the expand parameter will be ignored.

Source code in guitk/containers.py
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
def __init__(
    self,
    key: Hashable | None = None,
    height: int | None = None,
    padding: PaddingType | None = None,
    disabled: bool | None = False,
    sticky: str | None = "nsew",
    valign: VAlign | None = None,
    halign: HAlign | None = None,
    vexpand: bool = True,
    hexpand: bool = True,
    distribute: bool = False,
    vspacing: PadType | None = None,
    hspacing: PadType | None = None,
    vscrollbar: bool = False,
    # hscrollbar: bool = False,
    autohide_scrollbars: bool = True,
):
    """A container that stacks widgets horizontally when added to a Layout

    Args:
        key (Hashable, optional): The key to use for the HStack. Defaults to None.
        height (int, optional): The height of the HStack. Defaults to None.
        padding (PaddingType, optional): The padding around the HStack. Defaults to None.
        disabled (bool, optional): Whether the HStack is disabled. Defaults to False.
        sticky (str, optional): The sticky value for the HStack. Defaults to "nsew".
        valign (VAlign, optional): The vertical alignment for the widgets in the HStack.
            Defaults to None.
        halign (HAlign, optional): The horizontal alignment for the widgets in the HStack.
            Defaults to None.
        vexpand (bool, optional): Whether the Stack should expand vertically.
            Defaults to True.
        hexpand (bool, optional): Whether the Stack should expand horizontally.
            Defaults to True.
        distribute (bool, optional): Whether the HStack should distribute widgets evenly.
        vspacing (PadType, optional): Vertical spacing between widgets. Defaults to None.
        hspacing (PadType, optional): Horizontal spacing between widgets. Defaults to None.
        vscrollbar (bool): Whether to include a vertical scrollbar. Defaults to False.
        autohide_scrollbars (bool): Whether to hide scrollbars when not needed. Defaults to True.

    Note:
        If height is specified, the HStack will not expand to fill the available space and the
        expand parameter will be ignored.
    """
    super().__init__(
        key=key,
        height=height,
        width=None,
        padding=padding,
        disabled=disabled,
        sticky=sticky,
        valign=valign,
        halign=halign,
        vexpand=vexpand,
        hexpand=hexpand,
        distribute=distribute,
        vspacing=vspacing,
        hspacing=hspacing,
        vscrollbar=vscrollbar,
        # hscrollbar=hscrollbar,
        autohide_scrollbars=autohide_scrollbars,
    )

VStack

Bases: _Stack

A container that stacks widgets vertically when added to a Layout

Source code in guitk/containers.py
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
class VStack(_Stack):
    """A container that stacks widgets vertically when added to a Layout"""

    def __init__(
        self,
        key: Hashable | None = None,
        width: int | None = None,
        # height: int | None = None,
        padding: PaddingType | None = None,
        disabled: bool | None = False,
        sticky: str | None = "nsew",
        valign: VAlign | None = None,
        halign: HAlign | None = None,
        vexpand: bool = True,
        hexpand: bool = True,
        distribute: bool = False,
        vspacing: PadType | None = None,
        hspacing: PadType | None = None,
        vscrollbar: bool = False,
        # hscrollbar: bool = False,
        autohide_scrollbars: bool = True,
    ):
        """Base container container that stacks widgets vertically when added to a Layout

        Args:
            key (Hashable, optional): The key to use for the VStack. Defaults to None.
            width (int, optional): The width of the VStack. Defaults to None.
            padding (PaddingType, optional): The padding around the VStack. Defaults to None.
            disabled (bool, optional): Whether the VStack is disabled. Defaults to False.
            sticky (str, optional): The sticky value for the VStack. Defaults to "nsew".
            valign (VAlign, optional): The vertical alignment for the widgets in the VStack.
                Defaults to None.
            halign (HAlign, optional): The horizontal alignment for the widgets in the VStack.
                Defaults to None.
            vexpand (bool, optional): Whether the Stack should expand vertically.
                Defaults to True.
            hexpand (bool, optional): Whether the Stack should expand horizontally.
                Defaults to True.
            distribute (bool, optional): Whether the VStack should distribute widgets evenly.
            vspacing (PadType, optional): Vertical spacing between widgets. Defaults to None.
            hspacing (PadType, optional): Horizontal spacing between widgets. Defaults to None.
            vscrollbar (bool): Whether to include a vertical scrollbar. Defaults to False.
            autohide_scrollbars (bool): Whether to hide scrollbars when not needed. Defaults to True.

        Note:
            If width is specified, the VStack will not expand to fill the available space and the
            expand parameter will be ignored.
        """
        super().__init__(
            key=key,
            width=width,
            height=None,
            padding=padding,
            disabled=disabled,
            sticky=sticky,
            valign=valign,
            halign=halign,
            vexpand=vexpand,
            hexpand=hexpand,
            distribute=distribute,
            vspacing=vspacing,
            hspacing=hspacing,
            vscrollbar=vscrollbar,
            # hscrollbar=hscrollbar,
            autohide_scrollbars=autohide_scrollbars,
        )

__init__(key=None, width=None, padding=None, disabled=False, sticky='nsew', valign=None, halign=None, vexpand=True, hexpand=True, distribute=False, vspacing=None, hspacing=None, vscrollbar=False, autohide_scrollbars=True)

Base container container that stacks widgets vertically when added to a Layout

Parameters:

Name Type Description Default
key Hashable

The key to use for the VStack. Defaults to None.

None
width int

The width of the VStack. Defaults to None.

None
padding PaddingType

The padding around the VStack. Defaults to None.

None
disabled bool

Whether the VStack is disabled. Defaults to False.

False
sticky str

The sticky value for the VStack. Defaults to "nsew".

'nsew'
valign VAlign

The vertical alignment for the widgets in the VStack. Defaults to None.

None
halign HAlign

The horizontal alignment for the widgets in the VStack. Defaults to None.

None
vexpand bool

Whether the Stack should expand vertically. Defaults to True.

True
hexpand bool

Whether the Stack should expand horizontally. Defaults to True.

True
distribute bool

Whether the VStack should distribute widgets evenly.

False
vspacing PadType

Vertical spacing between widgets. Defaults to None.

None
hspacing PadType

Horizontal spacing between widgets. Defaults to None.

None
vscrollbar bool

Whether to include a vertical scrollbar. Defaults to False.

False
autohide_scrollbars bool

Whether to hide scrollbars when not needed. Defaults to True.

True
Note

If width is specified, the VStack will not expand to fill the available space and the expand parameter will be ignored.

Source code in guitk/containers.py
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
def __init__(
    self,
    key: Hashable | None = None,
    width: int | None = None,
    # height: int | None = None,
    padding: PaddingType | None = None,
    disabled: bool | None = False,
    sticky: str | None = "nsew",
    valign: VAlign | None = None,
    halign: HAlign | None = None,
    vexpand: bool = True,
    hexpand: bool = True,
    distribute: bool = False,
    vspacing: PadType | None = None,
    hspacing: PadType | None = None,
    vscrollbar: bool = False,
    # hscrollbar: bool = False,
    autohide_scrollbars: bool = True,
):
    """Base container container that stacks widgets vertically when added to a Layout

    Args:
        key (Hashable, optional): The key to use for the VStack. Defaults to None.
        width (int, optional): The width of the VStack. Defaults to None.
        padding (PaddingType, optional): The padding around the VStack. Defaults to None.
        disabled (bool, optional): Whether the VStack is disabled. Defaults to False.
        sticky (str, optional): The sticky value for the VStack. Defaults to "nsew".
        valign (VAlign, optional): The vertical alignment for the widgets in the VStack.
            Defaults to None.
        halign (HAlign, optional): The horizontal alignment for the widgets in the VStack.
            Defaults to None.
        vexpand (bool, optional): Whether the Stack should expand vertically.
            Defaults to True.
        hexpand (bool, optional): Whether the Stack should expand horizontally.
            Defaults to True.
        distribute (bool, optional): Whether the VStack should distribute widgets evenly.
        vspacing (PadType, optional): Vertical spacing between widgets. Defaults to None.
        hspacing (PadType, optional): Horizontal spacing between widgets. Defaults to None.
        vscrollbar (bool): Whether to include a vertical scrollbar. Defaults to False.
        autohide_scrollbars (bool): Whether to hide scrollbars when not needed. Defaults to True.

    Note:
        If width is specified, the VStack will not expand to fill the available space and the
        expand parameter will be ignored.
    """
    super().__init__(
        key=key,
        width=width,
        height=None,
        padding=padding,
        disabled=disabled,
        sticky=sticky,
        valign=valign,
        halign=halign,
        vexpand=vexpand,
        hexpand=hexpand,
        distribute=distribute,
        vspacing=vspacing,
        hspacing=hspacing,
        vscrollbar=vscrollbar,
        # hscrollbar=hscrollbar,
        autohide_scrollbars=autohide_scrollbars,
    )

HSpacer

Bases: Label

HSpacer widget that expands to fill the horizontal space in the layout

Source code in guitk/spacer.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class HSpacer(Label):
    """HSpacer widget that expands to fill the horizontal space in the layout"""

    def __init__(self, rowspan=1):
        super().__init__(
            "",
            padding=0,
            disabled=True,
            sticky="nsew",
            autoframe=False,
            borderwidth=debug_borderwidth() or None,
            relief=debug_relief() or None,
            weightx=1,
            rowspan=rowspan,
        )

    def _create_widget(self, parent: tk.BaseWidget, window: Window, row: int, col: int):
        super()._create_widget(parent, window, row, col)

VSpacer

Bases: Label

"HSpacer widget that expands to fill the vertical space in the layout

Source code in guitk/spacer.py
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class VSpacer(Label):
    """ "HSpacer widget that expands to fill the vertical space in the layout"""

    def __init__(self, columnspan=1):
        super().__init__(
            "",
            padding=0,
            disabled=True,
            sticky="nsew",
            autoframe=False,
            borderwidth=debug_borderwidth() or None,
            relief=debug_relief() or None,
            weighty=1,
            columnspan=columnspan,
        )

    def _create_widget(self, parent: tk.BaseWidget, window: Window, row: int, col: int):
        super()._create_widget(parent, window, row, col)

Button

Bases: BaseWidget

Basic button

Source code in guitk/ttk_button.py
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
class Button(BaseWidget):
    """Basic button"""

    def __init__(
        self,
        text: str,
        image: str | None = None,
        key: Hashable | None = None,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = True,
        sticky: str | None = None,
        tooltip: TooltipType | None = None,
        command: CommandType | None = None,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        """
        Initialize a Button widget.

        Args:
            text (str): Text for the button.
            image (str | None, optional): Image for the button. Defaults to None.
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to False.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            command (CommandType | None, optional): Command callback. Defaults to None.
            weightx (int | None, optional): Weight in x direction. Defaults to None.
            weighty (int | None, optional): Weight in y direction. Defaults to None.
            focus (bool, optional): If True, widget has focus. Defaults to False.
                Only one widget in a window can have focus.HLayout
            **kwargs: Additional keyword arguments are passed to ttk.Button.

        Note:
            Emits EventType.ButtonPress event.
        """
        super().__init__(
            key=key,
            disabled=disabled,
            rowspan=rowspan,
            columnspan=columnspan,
            padx=padx,
            pady=pady,
            events=events,
            sticky=sticky,
            tooltip=tooltip,
            command=command,
            weightx=weightx,
            weighty=weighty,
            focus=focus,
        )

        self.widget_type = "ttk.Button"
        self.text = text
        self.image = image
        self.key = key or text
        self.columnspan = columnspan
        self.rowspan = rowspan
        self.tooltip = tooltip
        self.padx = padx
        self.pady = pady
        self.kwargs = kwargs

    @property
    def value(self) -> str:
        return self.widget["text"]

    @value.setter
    def value(self, text: str):
        self.widget["text"] = text

    def _create_widget(self, parent: Any, window: Window, row: int, col: int):
        """Create the ttk.Button widget"""
        event = Event(self, window, self.key, EventType.ButtonPress)

        # build arg list for Button()
        kwargs_button = {
            k: v for k, v in self.kwargs.items() if k in _valid_ttk_button_attributes
        }

        if self.image:
            self._photoimage = load_image(self.image)
            kwargs_button["image"] = self._photoimage

        self.widget = ttk.Button(
            parent,
            text=self.text,
            command=window._make_callback(event),
            **kwargs_button,
        )
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )

        if self._command:
            self.events = True
            window._bind_command(
                EventCommand(
                    widget=self,
                    key=self.key,
                    event_type=EventType.ButtonPress,
                    command=self._command,
                )
            )

        if self._disabled:
            self.widget.state(["disabled"])

        return self.widget

    @property
    def button(self):
        """Return the Tk button widget"""
        return self.widget

button property

Return the Tk button widget

__init__(text, image=None, key=None, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=True, sticky=None, tooltip=None, command=None, weightx=None, weighty=None, focus=False, **kwargs)

Initialize a Button widget.

Parameters:

Name Type Description Default
text str

Text for the button.

required
image str | None

Image for the button. Defaults to None.

None
key Hashable

Unique key for this widget. Defaults to None.

None
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to False.

True
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
command CommandType | None

Command callback. Defaults to None.

None
weightx int | None

Weight in x direction. Defaults to None.

None
weighty int | None

Weight in y direction. Defaults to None.

None
focus bool

If True, widget has focus. Defaults to False. Only one widget in a window can have focus.HLayout

False
**kwargs

Additional keyword arguments are passed to ttk.Button.

{}
Note

Emits EventType.ButtonPress event.

Source code in guitk/ttk_button.py
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
def __init__(
    self,
    text: str,
    image: str | None = None,
    key: Hashable | None = None,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = True,
    sticky: str | None = None,
    tooltip: TooltipType | None = None,
    command: CommandType | None = None,
    weightx: int | None = None,
    weighty: int | None = None,
    focus: bool = False,
    **kwargs,
):
    """
    Initialize a Button widget.

    Args:
        text (str): Text for the button.
        image (str | None, optional): Image for the button. Defaults to None.
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to False.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        command (CommandType | None, optional): Command callback. Defaults to None.
        weightx (int | None, optional): Weight in x direction. Defaults to None.
        weighty (int | None, optional): Weight in y direction. Defaults to None.
        focus (bool, optional): If True, widget has focus. Defaults to False.
            Only one widget in a window can have focus.HLayout
        **kwargs: Additional keyword arguments are passed to ttk.Button.

    Note:
        Emits EventType.ButtonPress event.
    """
    super().__init__(
        key=key,
        disabled=disabled,
        rowspan=rowspan,
        columnspan=columnspan,
        padx=padx,
        pady=pady,
        events=events,
        sticky=sticky,
        tooltip=tooltip,
        command=command,
        weightx=weightx,
        weighty=weighty,
        focus=focus,
    )

    self.widget_type = "ttk.Button"
    self.text = text
    self.image = image
    self.key = key or text
    self.columnspan = columnspan
    self.rowspan = rowspan
    self.tooltip = tooltip
    self.padx = padx
    self.pady = pady
    self.kwargs = kwargs

BrowseFileButton

Bases: Button

Button that opens a file dialog to select a file.

Source code in guitk/ttk_button.py
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
class BrowseFileButton(Button):
    """Button that opens a file dialog to select a file."""

    def __init__(
        self,
        text="Browse",
        key: Hashable | None = None,
        target_key: Hashable | None = None,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = True,
        sticky: str | None = None,
        tooltip: TooltipType | None = None,
        filename_only: bool = False,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        """Initialize a BrowseFileButton widget.

        Args:
            text (str): Text for the button.
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            target_key (Hashable, optional): Unique key for the target widget. Defaults to None.
                If set, the target widget's value is set to the selected filename.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to False.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            filename_only (bool, optional): If True, only the filename is returned. Defaults to False.
            weightx (int | None, optional): Weight in x direction. Defaults to None.
            weighty (int | None, optional): Weight in y direction. Defaults to None.
            focus (bool, optional): If True, widget has focus. Defaults to False.
                Only one widget in a window can have focus.HLayout
            **kwargs: Additional keyword arguments are passed to ttk.Button or filedialog.askopenfilename as appropriate.

        Note:
            Emits a EventType.BrowseFile event after the file dialog is closed.
        """
        super().__init__(
            text,
            key=key,
            disabled=disabled,
            columnspan=columnspan,
            rowspan=rowspan,
            padx=padx,
            pady=pady,
            events=events,
            sticky=sticky,
            tooltip=tooltip,
            weightx=weightx,
            weighty=weighty,
            focus=focus,
        )
        self.target_key = target_key
        self.widget_type = "guitk.BrowseFileButton"
        self._filename = None
        self._filename_only = filename_only
        self.kwargs = kwargs

    def _create_widget(self, parent, window: "Window", row, col):
        kwargs_button = {
            k: v for k, v in self.kwargs.items() if k in _valid_ttk_button_attributes
        }
        self.widget = ttk.Button(
            parent, text=self.text, command=self.browse_dialog, **kwargs_button
        )
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )
        if self._disabled:
            self.widget.state(["disabled"])

        return self.widget

    @property
    def filename(self):
        return self._filename

    def browse_dialog(self):
        """Open a file dialog to select a file"""
        kwargs_options = {
            k: v for k, v in self.kwargs.items() if k in _valid_askopenfile_options
        }
        self._filename = filedialog.askopenfilename(**kwargs_options)
        if self._filename_only and self._filename:
            # only want the name, not the path
            self._filename = pathlib.Path(self._filename).name
        if self.target_key and self._filename:
            self.window[self.target_key].value = self._filename
        event = Event(self, self.window, self.key, EventType.BrowseFile)
        self.window._handle_event(event)

__init__(text='Browse', key=None, target_key=None, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=True, sticky=None, tooltip=None, filename_only=False, weightx=None, weighty=None, focus=False, **kwargs)

Initialize a BrowseFileButton widget.

Parameters:

Name Type Description Default
text str

Text for the button.

'Browse'
key Hashable

Unique key for this widget. Defaults to None.

None
target_key Hashable

Unique key for the target widget. Defaults to None. If set, the target widget's value is set to the selected filename.

None
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to False.

True
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
filename_only bool

If True, only the filename is returned. Defaults to False.

False
weightx int | None

Weight in x direction. Defaults to None.

None
weighty int | None

Weight in y direction. Defaults to None.

None
focus bool

If True, widget has focus. Defaults to False. Only one widget in a window can have focus.HLayout

False
**kwargs

Additional keyword arguments are passed to ttk.Button or filedialog.askopenfilename as appropriate.

{}
Note

Emits a EventType.BrowseFile event after the file dialog is closed.

Source code in guitk/ttk_button.py
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
def __init__(
    self,
    text="Browse",
    key: Hashable | None = None,
    target_key: Hashable | None = None,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = True,
    sticky: str | None = None,
    tooltip: TooltipType | None = None,
    filename_only: bool = False,
    weightx: int | None = None,
    weighty: int | None = None,
    focus: bool = False,
    **kwargs,
):
    """Initialize a BrowseFileButton widget.

    Args:
        text (str): Text for the button.
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        target_key (Hashable, optional): Unique key for the target widget. Defaults to None.
            If set, the target widget's value is set to the selected filename.
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to False.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        filename_only (bool, optional): If True, only the filename is returned. Defaults to False.
        weightx (int | None, optional): Weight in x direction. Defaults to None.
        weighty (int | None, optional): Weight in y direction. Defaults to None.
        focus (bool, optional): If True, widget has focus. Defaults to False.
            Only one widget in a window can have focus.HLayout
        **kwargs: Additional keyword arguments are passed to ttk.Button or filedialog.askopenfilename as appropriate.

    Note:
        Emits a EventType.BrowseFile event after the file dialog is closed.
    """
    super().__init__(
        text,
        key=key,
        disabled=disabled,
        columnspan=columnspan,
        rowspan=rowspan,
        padx=padx,
        pady=pady,
        events=events,
        sticky=sticky,
        tooltip=tooltip,
        weightx=weightx,
        weighty=weighty,
        focus=focus,
    )
    self.target_key = target_key
    self.widget_type = "guitk.BrowseFileButton"
    self._filename = None
    self._filename_only = filename_only
    self.kwargs = kwargs

browse_dialog()

Open a file dialog to select a file

Source code in guitk/ttk_button.py
264
265
266
267
268
269
270
271
272
273
274
275
276
def browse_dialog(self):
    """Open a file dialog to select a file"""
    kwargs_options = {
        k: v for k, v in self.kwargs.items() if k in _valid_askopenfile_options
    }
    self._filename = filedialog.askopenfilename(**kwargs_options)
    if self._filename_only and self._filename:
        # only want the name, not the path
        self._filename = pathlib.Path(self._filename).name
    if self.target_key and self._filename:
        self.window[self.target_key].value = self._filename
    event = Event(self, self.window, self.key, EventType.BrowseFile)
    self.window._handle_event(event)

BrowseDirectoryButton

Bases: Button

Button that opens a file dialog to select a directory.

Source code in guitk/ttk_button.py
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
class BrowseDirectoryButton(Button):
    """Button that opens a file dialog to select a directory."""

    def __init__(
        self,
        text="Browse",
        key: Hashable | None = None,
        target_key: Hashable | None = None,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = True,
        sticky: str | None = None,
        tooltip: TooltipType | None = None,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        """
        Initialize a BrowseDirectoryButton widget.

        Args:
            text (str): Text for the button.
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            target_key (Hashable, optional): Unique key for the target widget. Defaults to None.
                If set, the target widget's value is set to the selected directory.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to False.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            weightx (int | None, optional): Weight in x direction. Defaults to None.
            weighty (int | None, optional): Weight in y direction. Defaults to None.
            focus (bool, optional): If True, widget has focus. Defaults to False.
                Only one widget in a window can have focus.HLayout
            **kwargs: Additional keyword arguments are passed to ttk.Button or filedialog.askopenfilename as appropriate.

        Note:
            Emits a EventType.BrowseDirectory event after the file dialog is closed.
        """
        super().__init__(
            text,
            key=key,
            disabled=disabled,
            columnspan=columnspan,
            rowspan=rowspan,
            padx=padx,
            pady=pady,
            events=events,
            sticky=sticky,
            tooltip=tooltip,
            weightx=weightx,
            weighty=weighty,
            focus=focus,
        )
        self.target_key = target_key
        self.widget_type = "guitk.BrowseDirectoryButton"
        self._dirname = None
        self.kwargs = kwargs

    def _create_widget(self, parent, window: "Window", row, col):
        kwargs_button = {
            k: v for k, v in self.kwargs.items() if k in _valid_ttk_button_attributes
        }
        self.widget = ttk.Button(
            parent, text=self.text, command=self.browse_dialog, **kwargs_button
        )
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )
        if self._disabled:
            self.widget.state(["disabled"])

        return self.widget

    @property
    def directory(self):
        return self._dirname

    def browse_dialog(self):
        """
        Open a file dialog to select a directory.
        """
        kwargs_options = {
            k: v for k, v in self.kwargs.items() if k in _valid_askopenfile_options
        }
        self._dirname = filedialog.askdirectory(**kwargs_options)
        if self.target_key and self._dirname:
            self.window[self.target_key].value = self._dirname
        event = Event(self, self.window, self.key, EventType.BrowseDirectory)
        self.window._handle_event(event)

__init__(text='Browse', key=None, target_key=None, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=True, sticky=None, tooltip=None, weightx=None, weighty=None, focus=False, **kwargs)

Initialize a BrowseDirectoryButton widget.

Parameters:

Name Type Description Default
text str

Text for the button.

'Browse'
key Hashable

Unique key for this widget. Defaults to None.

None
target_key Hashable

Unique key for the target widget. Defaults to None. If set, the target widget's value is set to the selected directory.

None
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to False.

True
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
weightx int | None

Weight in x direction. Defaults to None.

None
weighty int | None

Weight in y direction. Defaults to None.

None
focus bool

If True, widget has focus. Defaults to False. Only one widget in a window can have focus.HLayout

False
**kwargs

Additional keyword arguments are passed to ttk.Button or filedialog.askopenfilename as appropriate.

{}
Note

Emits a EventType.BrowseDirectory event after the file dialog is closed.

Source code in guitk/ttk_button.py
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
def __init__(
    self,
    text="Browse",
    key: Hashable | None = None,
    target_key: Hashable | None = None,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = True,
    sticky: str | None = None,
    tooltip: TooltipType | None = None,
    weightx: int | None = None,
    weighty: int | None = None,
    focus: bool = False,
    **kwargs,
):
    """
    Initialize a BrowseDirectoryButton widget.

    Args:
        text (str): Text for the button.
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        target_key (Hashable, optional): Unique key for the target widget. Defaults to None.
            If set, the target widget's value is set to the selected directory.
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to False.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        weightx (int | None, optional): Weight in x direction. Defaults to None.
        weighty (int | None, optional): Weight in y direction. Defaults to None.
        focus (bool, optional): If True, widget has focus. Defaults to False.
            Only one widget in a window can have focus.HLayout
        **kwargs: Additional keyword arguments are passed to ttk.Button or filedialog.askopenfilename as appropriate.

    Note:
        Emits a EventType.BrowseDirectory event after the file dialog is closed.
    """
    super().__init__(
        text,
        key=key,
        disabled=disabled,
        columnspan=columnspan,
        rowspan=rowspan,
        padx=padx,
        pady=pady,
        events=events,
        sticky=sticky,
        tooltip=tooltip,
        weightx=weightx,
        weighty=weighty,
        focus=focus,
    )
    self.target_key = target_key
    self.widget_type = "guitk.BrowseDirectoryButton"
    self._dirname = None
    self.kwargs = kwargs

browse_dialog()

Open a file dialog to select a directory.

Source code in guitk/ttk_button.py
364
365
366
367
368
369
370
371
372
373
374
375
def browse_dialog(self):
    """
    Open a file dialog to select a directory.
    """
    kwargs_options = {
        k: v for k, v in self.kwargs.items() if k in _valid_askopenfile_options
    }
    self._dirname = filedialog.askdirectory(**kwargs_options)
    if self.target_key and self._dirname:
        self.window[self.target_key].value = self._dirname
    event = Event(self, self.window, self.key, EventType.BrowseDirectory)
    self.window._handle_event(event)

Checkbutton

Bases: BaseWidget

Checkbox / checkbutton

Source code in guitk/ttk_checkbutton.py
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
class Checkbutton(BaseWidget):
    """Checkbox / checkbutton"""

    def __init__(
        self,
        text: str,
        key: Hashable | None = None,
        checked: bool = False,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = True,
        sticky: str | None = None,
        tooltip: TooltipType | None = None,
        command: CommandType | None = None,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        """
        Initialize a ttk.Checkbutton widget.

        Args:
            text (str): Text for the checkbutton.
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            checked (bool, optional): Initial state. Defaults to False (not checked).
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to False.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            command (CommandType | None, optional): Command callback. Defaults to None.
            weightx (int | None, optional): Weight of widget in X direction. Defaults to None.
            weighty (int | None, optional): Weight of widget in Y direction. Defaults to None.
            focus (bool, optional): If True, widget has focus. Defaults to False.
                Only one widget in a window can have focus.HLayout
            **kwargs: Additional keyword arguments are passed to ttk.Checkbutton.

        Notes:
            Unlike a regular ttk.Checkbutton, the onvalue and offvalue are always True and False.
            Emits an EventType.Checkbutton event when the checkbutton is clicked.
        """
        super().__init__(
            key=key,
            disabled=disabled,
            rowspan=rowspan,
            columnspan=columnspan,
            padx=padx,
            pady=pady,
            events=events,
            sticky=sticky,
            tooltip=tooltip,
            command=command,
            weightx=weightx,
            weighty=weighty,
            focus=focus,
        )
        self.widget_type = "ttk.Checkbutton"
        self.text = text
        self.key = key or text
        self.columnspan = columnspan
        self.rowspan = rowspan
        self._value: tk.BooleanVar = tk.BooleanVar()
        self._checked = checked
        self.kwargs = kwargs

    def _create_widget(self, parent, window: Window, row, col):
        event = Event(self, window, self.key, EventType.Checkbutton)

        # build arg list for Checkbutton
        kwargs_checkbutton = {
            k: v
            for k, v in self.kwargs.items()
            if k in _valid_ttk_checkbutton_attributes
        }

        self.widget = ttk.Checkbutton(
            parent,
            text=self.text,
            anchor=self.kwargs.get("anchor"),
            command=window._make_callback(event),
            variable=self._value,
            onvalue=True,
            **kwargs_checkbutton,
        )
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )

        if self._command:
            self.events = True
            window._bind_command(
                EventCommand(
                    widget=self,
                    key=self.key,
                    event_type=EventType.Checkbutton,
                    command=self._command,
                )
            )

        if self._checked:
            self.widget.invoke()

        if self._disabled:
            self.widget.state(["disabled"])
        return self.widget

    @property
    def checkbutton(self):
        """Return the ttk.Checkbutton widget"""
        return self.widget

checkbutton property

Return the ttk.Checkbutton widget

__init__(text, key=None, checked=False, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=True, sticky=None, tooltip=None, command=None, weightx=None, weighty=None, focus=False, **kwargs)

Initialize a ttk.Checkbutton widget.

Parameters:

Name Type Description Default
text str

Text for the checkbutton.

required
key Hashable

Unique key for this widget. Defaults to None.

None
checked bool

Initial state. Defaults to False (not checked).

False
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to False.

True
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
command CommandType | None

Command callback. Defaults to None.

None
weightx int | None

Weight of widget in X direction. Defaults to None.

None
weighty int | None

Weight of widget in Y direction. Defaults to None.

None
focus bool

If True, widget has focus. Defaults to False. Only one widget in a window can have focus.HLayout

False
**kwargs

Additional keyword arguments are passed to ttk.Checkbutton.

{}
Notes

Unlike a regular ttk.Checkbutton, the onvalue and offvalue are always True and False. Emits an EventType.Checkbutton event when the checkbutton is clicked.

Source code in guitk/ttk_checkbutton.py
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def __init__(
    self,
    text: str,
    key: Hashable | None = None,
    checked: bool = False,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = True,
    sticky: str | None = None,
    tooltip: TooltipType | None = None,
    command: CommandType | None = None,
    weightx: int | None = None,
    weighty: int | None = None,
    focus: bool = False,
    **kwargs,
):
    """
    Initialize a ttk.Checkbutton widget.

    Args:
        text (str): Text for the checkbutton.
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        checked (bool, optional): Initial state. Defaults to False (not checked).
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to False.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        command (CommandType | None, optional): Command callback. Defaults to None.
        weightx (int | None, optional): Weight of widget in X direction. Defaults to None.
        weighty (int | None, optional): Weight of widget in Y direction. Defaults to None.
        focus (bool, optional): If True, widget has focus. Defaults to False.
            Only one widget in a window can have focus.HLayout
        **kwargs: Additional keyword arguments are passed to ttk.Checkbutton.

    Notes:
        Unlike a regular ttk.Checkbutton, the onvalue and offvalue are always True and False.
        Emits an EventType.Checkbutton event when the checkbutton is clicked.
    """
    super().__init__(
        key=key,
        disabled=disabled,
        rowspan=rowspan,
        columnspan=columnspan,
        padx=padx,
        pady=pady,
        events=events,
        sticky=sticky,
        tooltip=tooltip,
        command=command,
        weightx=weightx,
        weighty=weighty,
        focus=focus,
    )
    self.widget_type = "ttk.Checkbutton"
    self.text = text
    self.key = key or text
    self.columnspan = columnspan
    self.rowspan = rowspan
    self._value: tk.BooleanVar = tk.BooleanVar()
    self._checked = checked
    self.kwargs = kwargs

Combobox

Bases: BaseWidget

ttk Combobox

Source code in guitk/ttk_combobox.py
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
class Combobox(BaseWidget):
    """ttk Combobox"""

    def __init__(
        self,
        key: Hashable | None = None,
        default: str | None = None,
        values: list[str] | None = None,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = True,
        keyrelease: bool = False,
        sticky: str | None = None,
        tooltip: TooltipType | None = None,
        command: CommandType | None = None,
        readonly: bool = False,
        autosize: bool = False,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        super().__init__(
            key=key,
            disabled=disabled,
            columnspan=columnspan,
            rowspan=rowspan,
            padx=padx,
            pady=pady,
            events=events,
            sticky=sticky,
            tooltip=tooltip,
            command=command,
            weightx=weightx,
            weighty=weighty,
            focus=focus,
        )
        """
        Initialize a ttk.Combobox widget.

        Args:
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            default (str, optional): Default value. Defaults to None.
            values (list[str], optional): List of values for the combobox. Defaults to None.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to False.
            keyrelease (bool, optional): If True and events is True, emit EventType.KeyRelease event when a key is released.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            command (CommandType | None, optional): Command callback. Defaults to None.
            readonly (bool, optional): If True, widget is read-only. Defaults to False.
                If Combobox is not readonly, user can type in a value that is not in the list of values.
            autosize (bool, optional): If True, automatically set width to fit longest value. Defaults to False.
            weightx (int | None, optional): Weight of widget in X direction. Defaults to None.
            weighty (int | None, optional): Weight of widget in Y direction. Defaults to None.
            focus (bool, optional): If True, widget has focus. Defaults to False.
                Only one widget in a window can have focus.HLayout
            **kwargs: Additional keyword arguments are passed to ttk.Checkbutton.

        Note:
            Emits EventType.ComboboxSelected event when a value is selected from the list.
            Emits EventType.ComboboxReturn event when the Return key is pressed.
            Emits EventType.KeyRelease event when a key is released (if keyrelease is True).
        """
        self.widget_type = "ttk.Combobox"
        self.key = key or "Combobox"
        self.columnspan = columnspan
        self.rowspan = rowspan
        self._readonly = readonly
        self._autosize = autosize
        self.kwargs = kwargs
        self.values = values
        self.default = default
        self.keyrelease = keyrelease

    def _create_widget(self, parent, window: Window, row, col):
        # build arg list for Combobox
        kwargs = {
            k: v for k, v in self.kwargs.items() if k in _valid_ttk_combobox_attributes
        }

        if self._autosize:
            # automatically set width, override any width value provided
            width = len(max(self.values, key=len))
            kwargs["width"] = width + 1

        self.widget = ttk.Combobox(
            parent,
            textvariable=self._value,
            values=self.values,
            **kwargs,
        )
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )

        # bind events
        if self.keyrelease:
            event_release = Event(self, window, self.key, EventType.KeyRelease)
            self.widget.bind("<KeyRelease>", window._make_callback(event_release))

        event_selected = Event(self, window, self.key, EventType.ComboboxSelected)
        self.widget.bind("<<ComboboxSelected>>", window._make_callback(event_selected))

        combo_return_key = Event(self, window, self.key, EventType.ComboboxReturn)
        self.widget.bind("<Return>", window._make_callback(combo_return_key))

        if self._command:
            self.events = True
            window._bind_command(
                EventCommand(
                    widget=self,
                    key=self.key,
                    event_type=EventType.ComboboxSelected,
                    command=self._command,
                )
            )

        if self.default is not None:
            self.value = self.default

        if self._disabled:
            self.widget.state(["disabled"])

        if self._readonly:
            self.widget.state(["readonly"])

        return self.widget

    @property
    def combobox(self):
        """Return the Tk combobox widget"""
        return self.widget

combobox property

Return the Tk combobox widget

Entry

Bases: BaseWidget

ttk.Entry text entry / input box

Source code in guitk/ttk_entry.py
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
class Entry(BaseWidget):
    """ttk.Entry text entry / input box"""

    def __init__(
        self,
        key: Hashable | None = None,
        default: str | None = None,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = True,
        keyrelease: bool = False,
        sticky: str | None = None,
        tooltip: TooltipType = None,
        command: CommandType | None = None,
        hscrollbar: bool = False,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        """Initialize an Entry widget.

        Args:
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            default (str | None, optional): Default text for the entry box. Defaults to None.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to True.
            keyrelease (bool, optional): If True, generate events on key release. Defaults to False.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            command (CommandType | None, optional): Command callback. Defaults to None.
            hscrollbar (bool, optional): Show horizontal scrollbar. Defaults to False.
            weightx (int | None, optional): Weight for horizontal resizing. Defaults to None.
            weighty (int | None, optional): Weight for vertical resizing. Defaults to None.
            focus (bool, optional): If True, widget has focus. Defaults to False.
                Only one widget in a window can have focus.HLayout
            **kwargs: Additional keyword arguments are passed to ttk.Entry.

        Note:
            Emits EventType.EntryReturn event on return key press.
            If keyrelease is True, emits EventType.KeyRelease event on every key release.
        """
        super().__init__(
            key=key,
            disabled=disabled,
            columnspan=columnspan,
            rowspan=rowspan,
            padx=padx,
            pady=pady,
            events=events,
            sticky=sticky,
            tooltip=tooltip,
            command=command,
            weightx=weightx,
            weighty=weighty,
            focus=focus,
        )
        self.widget_type = "ttk.Entry"
        default = default or ""
        self._value.set(default)
        self.key = key or "Entry"
        self.columnspan = columnspan
        self.rowspan = rowspan
        self.hscrollbar = hscrollbar
        self.keyrelease = keyrelease
        self.kwargs = kwargs

    def _create_widget(self, parent, window: Window, row, col):
        # build arg list for ttk.Entry
        kwargs_entry = {
            k: v for k, v in self.kwargs.items() if k in _valid_ttk_entry_attributes
        }
        self.widget = scrolled_widget_factory(
            parent,
            ttk.Entry,
            hscrollbar=self.hscrollbar,
            textvariable=self._value,
            **kwargs_entry,
        )
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )

        # bind key release event
        if self.keyrelease:
            event = Event(self, window, self.key, EventType.KeyRelease)
            self.widget.bind("<KeyRelease>", window._make_callback(event))

        # bind return key event
        entry_return_key = Event(self, window, self.key, EventType.EntryReturn)
        self.widget.bind("<Return>", window._make_callback(entry_return_key))

        if self._command:
            self.events = True
            window._bind_command(
                EventCommand(
                    widget=self,
                    key=self.key,
                    event_type=EventType.KeyRelease,
                    command=self._command,
                )
            )

        if self._disabled:
            self.widget.state(["disabled"])

        return self.widget

    @property
    def entry(self):
        """Return the Tk entry widget"""
        return self.widget

entry property

Return the Tk entry widget

__init__(key=None, default=None, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=True, keyrelease=False, sticky=None, tooltip=None, command=None, hscrollbar=False, weightx=None, weighty=None, focus=False, **kwargs)

Initialize an Entry widget.

Parameters:

Name Type Description Default
key Hashable

Unique key for this widget. Defaults to None.

None
default str | None

Default text for the entry box. Defaults to None.

None
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to True.

True
keyrelease bool

If True, generate events on key release. Defaults to False.

False
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
command CommandType | None

Command callback. Defaults to None.

None
hscrollbar bool

Show horizontal scrollbar. Defaults to False.

False
weightx int | None

Weight for horizontal resizing. Defaults to None.

None
weighty int | None

Weight for vertical resizing. Defaults to None.

None
focus bool

If True, widget has focus. Defaults to False. Only one widget in a window can have focus.HLayout

False
**kwargs

Additional keyword arguments are passed to ttk.Entry.

{}
Note

Emits EventType.EntryReturn event on return key press. If keyrelease is True, emits EventType.KeyRelease event on every key release.

Source code in guitk/ttk_entry.py
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
def __init__(
    self,
    key: Hashable | None = None,
    default: str | None = None,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = True,
    keyrelease: bool = False,
    sticky: str | None = None,
    tooltip: TooltipType = None,
    command: CommandType | None = None,
    hscrollbar: bool = False,
    weightx: int | None = None,
    weighty: int | None = None,
    focus: bool = False,
    **kwargs,
):
    """Initialize an Entry widget.

    Args:
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        default (str | None, optional): Default text for the entry box. Defaults to None.
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to True.
        keyrelease (bool, optional): If True, generate events on key release. Defaults to False.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        command (CommandType | None, optional): Command callback. Defaults to None.
        hscrollbar (bool, optional): Show horizontal scrollbar. Defaults to False.
        weightx (int | None, optional): Weight for horizontal resizing. Defaults to None.
        weighty (int | None, optional): Weight for vertical resizing. Defaults to None.
        focus (bool, optional): If True, widget has focus. Defaults to False.
            Only one widget in a window can have focus.HLayout
        **kwargs: Additional keyword arguments are passed to ttk.Entry.

    Note:
        Emits EventType.EntryReturn event on return key press.
        If keyrelease is True, emits EventType.KeyRelease event on every key release.
    """
    super().__init__(
        key=key,
        disabled=disabled,
        columnspan=columnspan,
        rowspan=rowspan,
        padx=padx,
        pady=pady,
        events=events,
        sticky=sticky,
        tooltip=tooltip,
        command=command,
        weightx=weightx,
        weighty=weighty,
        focus=focus,
    )
    self.widget_type = "ttk.Entry"
    default = default or ""
    self._value.set(default)
    self.key = key or "Entry"
    self.columnspan = columnspan
    self.rowspan = rowspan
    self.hscrollbar = hscrollbar
    self.keyrelease = keyrelease
    self.kwargs = kwargs

LabelEntry

Bases: Entry

Text entry / input box with a label

Source code in guitk/ttk_entry.py
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
class LabelEntry(Entry):
    """Text entry / input box with a label"""

    # TODO: add option to put label above the entry box

    def __init__(
        self,
        text: str,
        key: Hashable | None = None,
        default: str | None = None,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = True,
        keyrelease: bool = False,
        sticky: str | None = None,
        tooltip: TooltipType = None,
        command: CommandType | None = None,
        hscrollbar: bool = False,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        """Initialize an Entry widget.

        Args:
            text (str): Label text.
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            default (str | None, optional): Default text for the entry box. Defaults to None.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to True.
            keyrelease (bool, optional): If True, emits EventType.KeyRelease event on every key release.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            command (CommandType | None, optional): Command callback. Defaults to None.
            hscrollbar (bool, optional): Show horizontal scrollbar. Defaults to False.
            weightx (int | None, optional): Weight for horizontal resizing. Defaults to None.
            weighty (int | None, optional): Weight for vertical resizing. Defaults to None.
            focus (bool, optional): If True, widget will have focus. Defaults to False. Only one widget can have focus.
            **kwargs: Additional keyword arguments are passed to ttk.Entry.

        Note:
            Emits EventType.EntryReturn event on return key press.
            If keyrelease is True, emits EventType.KeyRelease event on every key release.
        """
        super().__init__(
            key=key,
            default=default,
            disabled=disabled,
            columnspan=columnspan,
            rowspan=rowspan,
            padx=padx,
            pady=pady,
            events=events,
            keyrelease=keyrelease,
            sticky=sticky,
            tooltip=tooltip,
            command=command,
            hscrollbar=hscrollbar,
            focus=focus,
            weightx=weightx,
            weighty=weighty,
        )
        self.widget_type = "guitk.LabelEntry"
        self.text = text
        self.kwargs = kwargs

    def _create_widget(self, parent, window: "Window", row, col):
        # build arg list for Entry
        kwargs_entry = {
            k: v for k, v in self.kwargs.items() if k in _valid_ttk_entry_attributes
        }
        self.widget = _ttkLabelEntry(
            parent, text=self.text, textvariable=self._value, **kwargs_entry
        )
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )

        # bind key release event
        event = Event(self, window, self.key, EventType.KeyRelease)
        self.widget.bind("<KeyRelease>", window._make_callback(event))

        # bind return key event
        entry_return_key = Event(self, window, self.key, EventType.EntryReturn)
        self.widget.bind("<Return>", window._make_callback(entry_return_key))

        if self._command:
            self.events = True
            window._bind_command(
                EventCommand(
                    widget=self,
                    key=self.key,
                    event_type=EventType.KeyRelease,
                    command=self._command,
                )
            )

        if self._disabled:
            self.widget.state(["disabled"])

        return self.widget

    @property
    def entry(self):
        """Return the Tk entry widget"""
        return self.widget

entry property

Return the Tk entry widget

__init__(text, key=None, default=None, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=True, keyrelease=False, sticky=None, tooltip=None, command=None, hscrollbar=False, weightx=None, weighty=None, focus=False, **kwargs)

Initialize an Entry widget.

Parameters:

Name Type Description Default
text str

Label text.

required
key Hashable

Unique key for this widget. Defaults to None.

None
default str | None

Default text for the entry box. Defaults to None.

None
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to True.

True
keyrelease bool

If True, emits EventType.KeyRelease event on every key release.

False
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
command CommandType | None

Command callback. Defaults to None.

None
hscrollbar bool

Show horizontal scrollbar. Defaults to False.

False
weightx int | None

Weight for horizontal resizing. Defaults to None.

None
weighty int | None

Weight for vertical resizing. Defaults to None.

None
focus bool

If True, widget will have focus. Defaults to False. Only one widget can have focus.

False
**kwargs

Additional keyword arguments are passed to ttk.Entry.

{}
Note

Emits EventType.EntryReturn event on return key press. If keyrelease is True, emits EventType.KeyRelease event on every key release.

Source code in guitk/ttk_entry.py
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
def __init__(
    self,
    text: str,
    key: Hashable | None = None,
    default: str | None = None,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = True,
    keyrelease: bool = False,
    sticky: str | None = None,
    tooltip: TooltipType = None,
    command: CommandType | None = None,
    hscrollbar: bool = False,
    weightx: int | None = None,
    weighty: int | None = None,
    focus: bool = False,
    **kwargs,
):
    """Initialize an Entry widget.

    Args:
        text (str): Label text.
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        default (str | None, optional): Default text for the entry box. Defaults to None.
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to True.
        keyrelease (bool, optional): If True, emits EventType.KeyRelease event on every key release.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        command (CommandType | None, optional): Command callback. Defaults to None.
        hscrollbar (bool, optional): Show horizontal scrollbar. Defaults to False.
        weightx (int | None, optional): Weight for horizontal resizing. Defaults to None.
        weighty (int | None, optional): Weight for vertical resizing. Defaults to None.
        focus (bool, optional): If True, widget will have focus. Defaults to False. Only one widget can have focus.
        **kwargs: Additional keyword arguments are passed to ttk.Entry.

    Note:
        Emits EventType.EntryReturn event on return key press.
        If keyrelease is True, emits EventType.KeyRelease event on every key release.
    """
    super().__init__(
        key=key,
        default=default,
        disabled=disabled,
        columnspan=columnspan,
        rowspan=rowspan,
        padx=padx,
        pady=pady,
        events=events,
        keyrelease=keyrelease,
        sticky=sticky,
        tooltip=tooltip,
        command=command,
        hscrollbar=hscrollbar,
        focus=focus,
        weightx=weightx,
        weighty=weighty,
    )
    self.widget_type = "guitk.LabelEntry"
    self.text = text
    self.kwargs = kwargs

Label

Bases: BaseWidget

ttk.Label widget

Source code in guitk/ttk_label.py
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
class Label(BaseWidget):
    """ttk.Label widget"""

    def __init__(
        self,
        text: str,
        image: str | None = None,
        key: Hashable | None = None,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = False,
        sticky: str | None = None,
        tooltip: TooltipType = None,
        weightx: int | None = None,
        weighty: int | None = None,
        **kwargs,
    ):
        """
        Initialize a Label widget.

        Args:
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            text (str): Text to display in the label.
            image: (str, optional): Path to image to display in the label. Defaults to None.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to False.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            weightx (int | None, optional): Weight of this widget in the horizontal direction. Defaults to None.
            weighty (int | None, optional): Weight of this widget in the vertical direction. Defaults to None.
            **kwargs: Additional keyword arguments are passed to ttk.Entry.
        """
        super().__init__(
            key=key,
            disabled=disabled,
            rowspan=rowspan,
            columnspan=columnspan,
            padx=padx,
            pady=pady,
            events=events,
            sticky=sticky,
            tooltip=tooltip,
            weightx=weightx,
            weighty=weighty,
        )
        self.widget_type = "ttk.Label"
        self.text = text
        self.key = key or text
        self.columnspan = columnspan
        self.rowspan = rowspan
        self.image = image
        self.kwargs = kwargs

    def _create_widget(self, parent, window: Window, row, col):
        """Create the ttk.Label widget"""

        # Arg list for ttk.Label
        kwargs_label = {
            k: v for k, v in self.kwargs.items() if k in _valid_ttk_label_attributes
        }

        if self.image:
            self._photoimage = load_image(self.image)
            kwargs_label["image"] = self._photoimage

        self.widget = ttk.Label(
            parent,
            text=self.text,
            **kwargs_label,
        )
        self.widget["textvariable"] = self._value
        self._value.set(self.text)
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )
        if self._disabled:
            self.widget.state(["disabled"])
        return self.widget

    @property
    def label(self):
        """Return the Tk label widget"""
        return self.widget

label property

Return the Tk label widget

__init__(text, image=None, key=None, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=False, sticky=None, tooltip=None, weightx=None, weighty=None, **kwargs)

Initialize a Label widget.

Parameters:

Name Type Description Default
key Hashable

Unique key for this widget. Defaults to None.

None
text str

Text to display in the label.

required
image str | None

(str, optional): Path to image to display in the label. Defaults to None.

None
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to False.

False
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
weightx int | None

Weight of this widget in the horizontal direction. Defaults to None.

None
weighty int | None

Weight of this widget in the vertical direction. Defaults to None.

None
**kwargs

Additional keyword arguments are passed to ttk.Entry.

{}
Source code in guitk/ttk_label.py
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def __init__(
    self,
    text: str,
    image: str | None = None,
    key: Hashable | None = None,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = False,
    sticky: str | None = None,
    tooltip: TooltipType = None,
    weightx: int | None = None,
    weighty: int | None = None,
    **kwargs,
):
    """
    Initialize a Label widget.

    Args:
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        text (str): Text to display in the label.
        image: (str, optional): Path to image to display in the label. Defaults to None.
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to False.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        weightx (int | None, optional): Weight of this widget in the horizontal direction. Defaults to None.
        weighty (int | None, optional): Weight of this widget in the vertical direction. Defaults to None.
        **kwargs: Additional keyword arguments are passed to ttk.Entry.
    """
    super().__init__(
        key=key,
        disabled=disabled,
        rowspan=rowspan,
        columnspan=columnspan,
        padx=padx,
        pady=pady,
        events=events,
        sticky=sticky,
        tooltip=tooltip,
        weightx=weightx,
        weighty=weighty,
    )
    self.widget_type = "ttk.Label"
    self.text = text
    self.key = key or text
    self.columnspan = columnspan
    self.rowspan = rowspan
    self.image = image
    self.kwargs = kwargs

Notebook

Bases: _Container

ttk.Notebook widget

Source code in guitk/ttk_notebook.py
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
class Notebook(_Container):
    """ttk.Notebook widget"""

    def __init__(
        self,
        key: Hashable | None = None,
        tabs: list[HTab] | None = None,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = False,
        sticky: str | None = None,
        tooltip: TooltipType = None,
        command: CommandType | None = None,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        """Initialize a Notebook widget.

        Args:
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            tabs: (list[Tab], optional): Tabs to add to the notebook. Defaults to None.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to False.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            command (CommandType | None, optional): Command to execute when clicked. Defaults to None.
            weightx (int | None, optional): Horizontal weight. Defaults to None.
            weighty (int | None, optional): Vertical weight. Defaults to None.
            focus (bool, optional): If True, widget will have focus. Defaults to False.
                Only one widget in a window can have focus.HLayout
            **kwargs: Additional keyword arguments are passed to ttk.Entry.


        Note:
            Emits EventType.NotebookTabChanged event.
        """
        super().__init__(
            frametype=GUITK.ELEMENT_FRAME,
            key=None,
            width=None,
            height=None,
            layout=None,
            style=None,
            borderwidth=None,
            padding=0,
            relief=None,
            disabled=disabled,
            rowspan=None,
            columnspan=None,
            sticky=sticky,
            tooltip=None,
            autoframe=False,
            padx=0,
            pady=0,
            weightx=weightx,
            weighty=weighty,
            focus=focus,
        )
        self.widget_type = "ttk.Notebook"
        self.key = key or "Notebook"
        self.columnspan = columnspan
        self.rowspan = rowspan
        self.tabs = tabs or []
        self._command = command
        self.kwargs = kwargs
        self._tab_count = 0

    def _create_widget(self, parent, window: "Window", row, col):
        # Arg list for ttk.Label
        kwargs_notebook = {
            k: v for k, v in self.kwargs.items() if k in _valid_ttk_notebook_attributes
        }

        self.widget = ttk.Notebook(parent, **kwargs_notebook)
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )

        event_tab_change = Event(self, window, self.key, EventType.NotebookTabChanged)
        self.widget.bind(
            "<<NotebookTabChanged>>", window._make_callback(event_tab_change)
        )

        if self.layout:
            for row in self.layout:
                for tab in row:
                    self.add(tab)

        if self._command:
            self.events = True
            window._bind_command(
                # the actual widget will be a tk widget in form widget=.!toplevel.!frame.!notebook, so it won't match self.widget
                # so set widget=None or _handle_commands won't correctly handle the command
                EventCommand(
                    widget=self,
                    key=self.key,
                    event_type=EventType.NotebookTabChanged,
                    command=self._command,
                )
            )

        if self.width or self.height:
            self.widget.grid_propagate(0)

        if self._disabled:
            self.widget.state(["disabled"])

        return self.widget

    @property
    def current_tab(self):
        """Return the name of the currently selected tab"""
        return self.notebook.tab(self.notebook.select(), "text")

    def add(self, tab: HTab):
        """Add a Tab to the Notebook as new tab"""
        tab_ = tab._create_widget(self.widget, self.window, 0, 0)
        tab.kwargs["text"] = tab.name
        self.notebook.add(tab_, **tab.kwargs)

    def insert(self, pos, tab: HTab):
        """Insert a layout to the Notebook as new tab at position pos"""
        tab_ = tab._create_widget(self.widget, self.window, 0, 0)
        tab.kwargs["text"] = tab.name
        self.notebook.insert(pos, tab_, **tab.kwargs)

    @property
    def notebook(self):
        """Return the ttk.Notebook widget"""
        return self.widget

current_tab property

Return the name of the currently selected tab

notebook property

Return the ttk.Notebook widget

__init__(key=None, tabs=None, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=False, sticky=None, tooltip=None, command=None, weightx=None, weighty=None, focus=False, **kwargs)

Initialize a Notebook widget.

Parameters:

Name Type Description Default
key Hashable

Unique key for this widget. Defaults to None.

None
tabs list[HTab] | None

(list[Tab], optional): Tabs to add to the notebook. Defaults to None.

None
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to False.

False
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
command CommandType | None

Command to execute when clicked. Defaults to None.

None
weightx int | None

Horizontal weight. Defaults to None.

None
weighty int | None

Vertical weight. Defaults to None.

None
focus bool

If True, widget will have focus. Defaults to False. Only one widget in a window can have focus.HLayout

False
**kwargs

Additional keyword arguments are passed to ttk.Entry.

{}
Note

Emits EventType.NotebookTabChanged event.

Source code in guitk/ttk_notebook.py
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
def __init__(
    self,
    key: Hashable | None = None,
    tabs: list[HTab] | None = None,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = False,
    sticky: str | None = None,
    tooltip: TooltipType = None,
    command: CommandType | None = None,
    weightx: int | None = None,
    weighty: int | None = None,
    focus: bool = False,
    **kwargs,
):
    """Initialize a Notebook widget.

    Args:
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        tabs: (list[Tab], optional): Tabs to add to the notebook. Defaults to None.
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to False.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        command (CommandType | None, optional): Command to execute when clicked. Defaults to None.
        weightx (int | None, optional): Horizontal weight. Defaults to None.
        weighty (int | None, optional): Vertical weight. Defaults to None.
        focus (bool, optional): If True, widget will have focus. Defaults to False.
            Only one widget in a window can have focus.HLayout
        **kwargs: Additional keyword arguments are passed to ttk.Entry.


    Note:
        Emits EventType.NotebookTabChanged event.
    """
    super().__init__(
        frametype=GUITK.ELEMENT_FRAME,
        key=None,
        width=None,
        height=None,
        layout=None,
        style=None,
        borderwidth=None,
        padding=0,
        relief=None,
        disabled=disabled,
        rowspan=None,
        columnspan=None,
        sticky=sticky,
        tooltip=None,
        autoframe=False,
        padx=0,
        pady=0,
        weightx=weightx,
        weighty=weighty,
        focus=focus,
    )
    self.widget_type = "ttk.Notebook"
    self.key = key or "Notebook"
    self.columnspan = columnspan
    self.rowspan = rowspan
    self.tabs = tabs or []
    self._command = command
    self.kwargs = kwargs
    self._tab_count = 0

add(tab)

Add a Tab to the Notebook as new tab

Source code in guitk/ttk_notebook.py
162
163
164
165
166
def add(self, tab: HTab):
    """Add a Tab to the Notebook as new tab"""
    tab_ = tab._create_widget(self.widget, self.window, 0, 0)
    tab.kwargs["text"] = tab.name
    self.notebook.add(tab_, **tab.kwargs)

insert(pos, tab)

Insert a layout to the Notebook as new tab at position pos

Source code in guitk/ttk_notebook.py
168
169
170
171
172
def insert(self, pos, tab: HTab):
    """Insert a layout to the Notebook as new tab at position pos"""
    tab_ = tab._create_widget(self.widget, self.window, 0, 0)
    tab.kwargs["text"] = tab.name
    self.notebook.insert(pos, tab_, **tab.kwargs)

HTab

Bases: _Container

Tab for Notebook widget that arranges its widgets horizontally

Source code in guitk/ttk_notebook.py
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
class HTab(_Container):
    """Tab for Notebook widget that arranges its widgets horizontally"""

    def __init__(
        self,
        name=None,
        sticky: str | None = "nsew",
        valign: VAlign | None = None,
        halign: HAlign | None = None,
        **kwargs,
    ):
        """Initialize a horizontal Tab

        Args:
            name (str, optional): Name of the tab. Defaults to None.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            valign (VAlign | None, optional): Vertical alignment of widgets in the tab. Defaults to None.
            halign (HAlign | None, optional): Horizontal alignment of widgets in the tab. Defaults to None.
            **kwargs: Additional keyword arguments are passed to ttk.Frame.
        """

        super().__init__(
            frametype=GUITK.ELEMENT_FRAME,
            key=None,
            width=None,
            height=None,
            layout=None,
            style=None,
            borderwidth=None,
            padding=0,
            relief=None,
            disabled=False,
            rowspan=None,
            columnspan=None,
            sticky=sticky,
            tooltip=None,
            autoframe=True,
            valign=valign,
            halign=halign,
            padx=0,
            pady=0,
        )
        self.name = name
        self.kwargs = kwargs

__init__(name=None, sticky='nsew', valign=None, halign=None, **kwargs)

Initialize a horizontal Tab

Parameters:

Name Type Description Default
name str

Name of the tab. Defaults to None.

None
sticky str | None

Sticky direction for widget layout. Defaults to None.

'nsew'
valign VAlign | None

Vertical alignment of widgets in the tab. Defaults to None.

None
halign HAlign | None

Horizontal alignment of widgets in the tab. Defaults to None.

None
**kwargs

Additional keyword arguments are passed to ttk.Frame.

{}
Source code in guitk/ttk_notebook.py
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
def __init__(
    self,
    name=None,
    sticky: str | None = "nsew",
    valign: VAlign | None = None,
    halign: HAlign | None = None,
    **kwargs,
):
    """Initialize a horizontal Tab

    Args:
        name (str, optional): Name of the tab. Defaults to None.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        valign (VAlign | None, optional): Vertical alignment of widgets in the tab. Defaults to None.
        halign (HAlign | None, optional): Horizontal alignment of widgets in the tab. Defaults to None.
        **kwargs: Additional keyword arguments are passed to ttk.Frame.
    """

    super().__init__(
        frametype=GUITK.ELEMENT_FRAME,
        key=None,
        width=None,
        height=None,
        layout=None,
        style=None,
        borderwidth=None,
        padding=0,
        relief=None,
        disabled=False,
        rowspan=None,
        columnspan=None,
        sticky=sticky,
        tooltip=None,
        autoframe=True,
        valign=valign,
        halign=halign,
        padx=0,
        pady=0,
    )
    self.name = name
    self.kwargs = kwargs

VTab

Bases: HTab, _VerticalContainer

Tab for Notebook widget that arranges its widgets vertically

Source code in guitk/ttk_notebook.py
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
class VTab(HTab, _VerticalContainer):
    """Tab for Notebook widget that arranges its widgets vertically"""

    def __init__(
        self,
        name=None,
        sticky: str | None = "nsew",
        valign: VAlign | None = None,
        halign: HAlign | None = None,
        **kwargs,
    ):
        """Initialize a vertical Tab

        Args:
            name (str, optional): Name of the tab. Defaults to None.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            valign (VAlign | None, optional): Vertical alignment of widgets in the tab. Defaults to None.
            halign (HAlign | None, optional): Horizontal alignment of widgets in the tab. Defaults to None.
            **kwargs: Additional keyword arguments are passed to ttk.Frame.
        """

        super().__init__(
            frametype=GUITK.ELEMENT_FRAME,
            key=None,
            width=None,
            height=None,
            layout=None,
            style=None,
            borderwidth=None,
            padding=0,
            relief=None,
            disabled=False,
            rowspan=None,
            columnspan=None,
            sticky=sticky,
            tooltip=None,
            autoframe=True,
            padx=0,
            pady=0,
            valign=valign,
            halign=halign,
        )
        self.name = name
        self.kwargs = kwargs

__init__(name=None, sticky='nsew', valign=None, halign=None, **kwargs)

Initialize a vertical Tab

Parameters:

Name Type Description Default
name str

Name of the tab. Defaults to None.

None
sticky str | None

Sticky direction for widget layout. Defaults to None.

'nsew'
valign VAlign | None

Vertical alignment of widgets in the tab. Defaults to None.

None
halign HAlign | None

Horizontal alignment of widgets in the tab. Defaults to None.

None
**kwargs

Additional keyword arguments are passed to ttk.Frame.

{}
Source code in guitk/ttk_notebook.py
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
def __init__(
    self,
    name=None,
    sticky: str | None = "nsew",
    valign: VAlign | None = None,
    halign: HAlign | None = None,
    **kwargs,
):
    """Initialize a vertical Tab

    Args:
        name (str, optional): Name of the tab. Defaults to None.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        valign (VAlign | None, optional): Vertical alignment of widgets in the tab. Defaults to None.
        halign (HAlign | None, optional): Horizontal alignment of widgets in the tab. Defaults to None.
        **kwargs: Additional keyword arguments are passed to ttk.Frame.
    """

    super().__init__(
        frametype=GUITK.ELEMENT_FRAME,
        key=None,
        width=None,
        height=None,
        layout=None,
        style=None,
        borderwidth=None,
        padding=0,
        relief=None,
        disabled=False,
        rowspan=None,
        columnspan=None,
        sticky=sticky,
        tooltip=None,
        autoframe=True,
        padx=0,
        pady=0,
        valign=valign,
        halign=halign,
    )
    self.name = name
    self.kwargs = kwargs

Text

Bases: BaseWidget

A tk Text box

Source code in guitk/tk_text.py
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
class Text(BaseWidget):
    """A tk Text box"""

    def __init__(
        self,
        text: str | None = None,
        key: Hashable | None = None,
        width: int = 40,
        height: int = 20,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = False,
        sticky: str | None = None,
        tooltip: TooltipType = None,
        command: CommandType | None = None,
        vscrollbar: bool = False,
        hscrollbar: bool = False,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        """
        Initialize a Text widget.

        Args:
            text (str | None, optional): Default text for the text box. Defaults to None.
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            width (int, optional): Width of the text box. Defaults to 40.
            height (int, optional): Height of the text box. Defaults to 20.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to False.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            command (CommandType | None, optional): Command callback. Defaults to None.
            vscrollbar (bool, optional): Show vertical scrollbar. Defaults to False.
            hscrollbar (bool, optional): Show horizontal scrollbar. Defaults to False.
            weightx (int | None, optional): Weight of the widget in the x direction. Defaults to None.
            weighty (int | None, optional): Weight of the widget in the y direction. Defaults to None.
            focus (bool, optional): If True, widget has focus. Defaults to False.
                Only one widget in a window can have focus.HLayout
            **kwargs: Additional keyword arguments are passed to tk Text.

        Note:
            Emits EventType.KeyRelease events when the text is changed and events is True.
        """
        super().__init__(
            key=key,
            disabled=disabled,
            rowspan=rowspan,
            columnspan=columnspan,
            padx=padx,
            pady=pady,
            events=events,
            sticky=sticky,
            tooltip=tooltip,
            command=command,
            weightx=weightx,
            weighty=weighty,
            focus=focus,
        )
        self.widget_type = "tk.Text"
        self.key = key or "Text"
        self.width = width
        self.height = height
        self._value = text if text is not None else ""
        self.columnspan = columnspan
        self.rowspan = rowspan
        self.vscrollbar = vscrollbar
        self.hscrollbar = hscrollbar
        self.kwargs = kwargs

    def _create_widget(self, parent, window: "Window", row, col):
        kwargs_text = {
            k: v for k, v in self.kwargs.items() if k in _valid_tk_text_attributes
        }
        self.widget = scrolled_widget_factory(
            parent,
            tk.Text,
            vscrollbar=self.vscrollbar,
            hscrollbar=self.hscrollbar,
            width=self.width,
            height=self.height,
            **kwargs_text,
        )
        self._grid(
            row=row, column=col, rowspan=self.rowspan, columnspan=self.columnspan
        )

        event = Event(self, window, self.key, EventType.KeyRelease)
        self.widget.bind("<KeyRelease>", window._make_callback(event))

        self.value = self._value

        if self._command:
            self.events = True
            window._bind_command(
                EventCommand(
                    widget=self,
                    key=self.key,
                    event_type=EventType.KeyRelease,
                    command=self._command,
                )
            )

        if self._disabled:
            self.widget["state"] = "disabled"

        return self.widget

    @property
    def value(self):
        return self.widget.get("1.0", tk.END).rstrip()

    @value.setter
    def value(self, text):
        self.widget.delete("1.0", tk.END)
        self.widget.insert("1.0", text)

    @property
    def text(self):
        """Return the Tk text widget"""
        return self.widget

text property

Return the Tk text widget

__init__(text=None, key=None, width=40, height=20, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=False, sticky=None, tooltip=None, command=None, vscrollbar=False, hscrollbar=False, weightx=None, weighty=None, focus=False, **kwargs)

Initialize a Text widget.

Parameters:

Name Type Description Default
text str | None

Default text for the text box. Defaults to None.

None
key Hashable

Unique key for this widget. Defaults to None.

None
width int

Width of the text box. Defaults to 40.

40
height int

Height of the text box. Defaults to 20.

20
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to False.

False
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
command CommandType | None

Command callback. Defaults to None.

None
vscrollbar bool

Show vertical scrollbar. Defaults to False.

False
hscrollbar bool

Show horizontal scrollbar. Defaults to False.

False
weightx int | None

Weight of the widget in the x direction. Defaults to None.

None
weighty int | None

Weight of the widget in the y direction. Defaults to None.

None
focus bool

If True, widget has focus. Defaults to False. Only one widget in a window can have focus.HLayout

False
**kwargs

Additional keyword arguments are passed to tk Text.

{}
Note

Emits EventType.KeyRelease events when the text is changed and events is True.

Source code in guitk/tk_text.py
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
def __init__(
    self,
    text: str | None = None,
    key: Hashable | None = None,
    width: int = 40,
    height: int = 20,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = False,
    sticky: str | None = None,
    tooltip: TooltipType = None,
    command: CommandType | None = None,
    vscrollbar: bool = False,
    hscrollbar: bool = False,
    weightx: int | None = None,
    weighty: int | None = None,
    focus: bool = False,
    **kwargs,
):
    """
    Initialize a Text widget.

    Args:
        text (str | None, optional): Default text for the text box. Defaults to None.
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        width (int, optional): Width of the text box. Defaults to 40.
        height (int, optional): Height of the text box. Defaults to 20.
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to False.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        command (CommandType | None, optional): Command callback. Defaults to None.
        vscrollbar (bool, optional): Show vertical scrollbar. Defaults to False.
        hscrollbar (bool, optional): Show horizontal scrollbar. Defaults to False.
        weightx (int | None, optional): Weight of the widget in the x direction. Defaults to None.
        weighty (int | None, optional): Weight of the widget in the y direction. Defaults to None.
        focus (bool, optional): If True, widget has focus. Defaults to False.
            Only one widget in a window can have focus.HLayout
        **kwargs: Additional keyword arguments are passed to tk Text.

    Note:
        Emits EventType.KeyRelease events when the text is changed and events is True.
    """
    super().__init__(
        key=key,
        disabled=disabled,
        rowspan=rowspan,
        columnspan=columnspan,
        padx=padx,
        pady=pady,
        events=events,
        sticky=sticky,
        tooltip=tooltip,
        command=command,
        weightx=weightx,
        weighty=weighty,
        focus=focus,
    )
    self.widget_type = "tk.Text"
    self.key = key or "Text"
    self.width = width
    self.height = height
    self._value = text if text is not None else ""
    self.columnspan = columnspan
    self.rowspan = rowspan
    self.vscrollbar = vscrollbar
    self.hscrollbar = hscrollbar
    self.kwargs = kwargs

Output

Bases: Text

Text box that redirects stderr and/or stdout to the text box.

Source code in guitk/tk_text.py
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
class Output(Text):
    """Text box that redirects stderr and/or stdout to the text box."""

    def __init__(
        self,
        text: str | None = None,
        key: Hashable | None = None,
        width: int = 40,
        height: int = 20,
        disabled: bool = False,
        columnspan: int | None = None,
        rowspan: int | None = None,
        padx: PadType | None = None,
        pady: PadType | None = None,
        events: bool = False,
        sticky: str | None = None,
        tooltip: TooltipType = None,
        vscrollbar: bool = True,
        hscrollbar: bool = False,
        stdout: bool = True,
        stderr: bool = True,
        echo: bool = False,
        weightx: int | None = None,
        weighty: int | None = None,
        focus: bool = False,
        **kwargs,
    ):
        """
        Initialize an Output widget.

        Args:
            text (str | None, optional): Default text for the text box. Defaults to None.
            key (Hashable, optional): Unique key for this widget. Defaults to None.
            width (int, optional): Width of the text box. Defaults to 40.
            height (int, optional): Height of the text box. Defaults to 20.
            disabled (bool, optional): If True, widget is disabled. Defaults to False.
            columnspan (int | None, optional): Number of columns to span. Defaults to None.
            rowspan (int | None, optional): Number of rows to span. Defaults to None.
            padx (PadType | None, optional): X padding. Defaults to None.
            pady (PadType | None, optional): Y padding. Defaults to None.
            events (bool, optional): Enable events for this widget. Defaults to False.
            sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
            tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
            command (CommandType | None, optional): Command callback. Defaults to None.
            vscrollbar (bool, optional): Show vertical scrollbar. Defaults to False.
            hscrollbar (bool, optional): Show horizontal scrollbar. Defaults to False.
            stdout (bool, optional): Redirect stdout to the text box. Defaults to True.
            stderr (bool, optional): Redirect stderr to the text box. Defaults to True.
            echo (bool, optional): Echo stdout and stderr to the console. Defaults to False.
            weightx (int | None, optional): Weight of the widget in the x direction. Defaults to None.
            weighty (int | None, optional): Weight of the widget in the y direction. Defaults to None.
            focus (bool, optional): If True, widget has focus. Defaults to False.
                Only one widget in a window can have focus.HLayout
            **kwargs: Additional keyword arguments are passed to tk Text.
        """
        super().__init__(
            text=text,
            key=key,
            width=width,
            height=height,
            disabled=disabled,
            rowspan=rowspan,
            columnspan=columnspan,
            padx=padx,
            pady=pady,
            events=events,
            sticky=sticky,
            tooltip=tooltip,
            vscrollbar=vscrollbar,
            hscrollbar=hscrollbar,
            weightx=weightx,
            weighty=weighty,
            focus=focus,
            **kwargs,
        )

        self.kwargs = kwargs
        self._echo = echo
        self._stdout = stdout
        self._stderr = stderr

        # stores state for stdout and stderr redirection
        self._redirect = []
        self._redirect_id = {}

    def _create_widget(self, parent, window: "Window", row, col):
        self.widget = super()._create_widget(parent, window, row, col)

        # Unbind <KeyRelease> since this isn't for user input
        self.widget.unbind("<KeyRelease>")

        if self.events:
            event = Event(self, window, self.key, EventType.OutputWrite)
            self.window.root.bind_all(
                EventType.OutputWrite.value, window._make_callback(event)
            )

        self._configure_redirect()
        self.enable_redirect()

        return self.widget

    def _configure_redirect(self):
        """Configure stdout and stderr redirection."""
        if self._stdout:
            self._redirect.append(StdOutRedirect())
        if self._stderr:
            self._redirect.append(StdErrRedirect())
        for r in self._redirect:
            r.echo = self._echo
            self._redirect_id[r] = r.register(self._write)

    def _write(self, line):
        with contextlib.suppress(tk.TclError):
            # ignore TclError if widget has been destroyed while trying to write
            self.text.insert(tk.END, line)
            self.text.yview(tk.END)
        self.window.root.event_generate(EventType.OutputWrite.value)

    @property
    def echo(self):
        """Return True if stdout and stderr are echoed to the console."""
        return self._echo

    @echo.setter
    def echo(self, echo):
        """Set whether stdout and stderr are echoed to the console."""
        self._echo = echo
        for r in self._redirect:
            r.echo = echo

    def disable_redirect(self):
        """Disable redirecting stdout and stderr to the text box."""
        for r in self._redirect:
            r.disable_redirect()

    def enable_redirect(self):
        """Enable redirecting stdout and stderr to the text box."""
        for r in self._redirect:
            r.enable_redirect()

    def __del__(self):
        for r, id_ in self._redirect_id.items():
            r.deregister(id_)

echo property writable

Return True if stdout and stderr are echoed to the console.

__init__(text=None, key=None, width=40, height=20, disabled=False, columnspan=None, rowspan=None, padx=None, pady=None, events=False, sticky=None, tooltip=None, vscrollbar=True, hscrollbar=False, stdout=True, stderr=True, echo=False, weightx=None, weighty=None, focus=False, **kwargs)

Initialize an Output widget.

Parameters:

Name Type Description Default
text str | None

Default text for the text box. Defaults to None.

None
key Hashable

Unique key for this widget. Defaults to None.

None
width int

Width of the text box. Defaults to 40.

40
height int

Height of the text box. Defaults to 20.

20
disabled bool

If True, widget is disabled. Defaults to False.

False
columnspan int | None

Number of columns to span. Defaults to None.

None
rowspan int | None

Number of rows to span. Defaults to None.

None
padx PadType | None

X padding. Defaults to None.

None
pady PadType | None

Y padding. Defaults to None.

None
events bool

Enable events for this widget. Defaults to False.

False
sticky str | None

Sticky direction for widget layout. Defaults to None.

None
tooltip TooltipType | None

Tooltip text or callback to generate tooltip text. Defaults to None.

None
command CommandType | None

Command callback. Defaults to None.

required
vscrollbar bool

Show vertical scrollbar. Defaults to False.

True
hscrollbar bool

Show horizontal scrollbar. Defaults to False.

False
stdout bool

Redirect stdout to the text box. Defaults to True.

True
stderr bool

Redirect stderr to the text box. Defaults to True.

True
echo bool

Echo stdout and stderr to the console. Defaults to False.

False
weightx int | None

Weight of the widget in the x direction. Defaults to None.

None
weighty int | None

Weight of the widget in the y direction. Defaults to None.

None
focus bool

If True, widget has focus. Defaults to False. Only one widget in a window can have focus.HLayout

False
**kwargs

Additional keyword arguments are passed to tk Text.

{}
Source code in guitk/tk_text.py
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
def __init__(
    self,
    text: str | None = None,
    key: Hashable | None = None,
    width: int = 40,
    height: int = 20,
    disabled: bool = False,
    columnspan: int | None = None,
    rowspan: int | None = None,
    padx: PadType | None = None,
    pady: PadType | None = None,
    events: bool = False,
    sticky: str | None = None,
    tooltip: TooltipType = None,
    vscrollbar: bool = True,
    hscrollbar: bool = False,
    stdout: bool = True,
    stderr: bool = True,
    echo: bool = False,
    weightx: int | None = None,
    weighty: int | None = None,
    focus: bool = False,
    **kwargs,
):
    """
    Initialize an Output widget.

    Args:
        text (str | None, optional): Default text for the text box. Defaults to None.
        key (Hashable, optional): Unique key for this widget. Defaults to None.
        width (int, optional): Width of the text box. Defaults to 40.
        height (int, optional): Height of the text box. Defaults to 20.
        disabled (bool, optional): If True, widget is disabled. Defaults to False.
        columnspan (int | None, optional): Number of columns to span. Defaults to None.
        rowspan (int | None, optional): Number of rows to span. Defaults to None.
        padx (PadType | None, optional): X padding. Defaults to None.
        pady (PadType | None, optional): Y padding. Defaults to None.
        events (bool, optional): Enable events for this widget. Defaults to False.
        sticky (str | None, optional): Sticky direction for widget layout. Defaults to None.
        tooltip (TooltipType | None, optional): Tooltip text or callback to generate tooltip text. Defaults to None.
        command (CommandType | None, optional): Command callback. Defaults to None.
        vscrollbar (bool, optional): Show vertical scrollbar. Defaults to False.
        hscrollbar (bool, optional): Show horizontal scrollbar. Defaults to False.
        stdout (bool, optional): Redirect stdout to the text box. Defaults to True.
        stderr (bool, optional): Redirect stderr to the text box. Defaults to True.
        echo (bool, optional): Echo stdout and stderr to the console. Defaults to False.
        weightx (int | None, optional): Weight of the widget in the x direction. Defaults to None.
        weighty (int | None, optional): Weight of the widget in the y direction. Defaults to None.
        focus (bool, optional): If True, widget has focus. Defaults to False.
            Only one widget in a window can have focus.HLayout
        **kwargs: Additional keyword arguments are passed to tk Text.
    """
    super().__init__(
        text=text,
        key=key,
        width=width,
        height=height,
        disabled=disabled,
        rowspan=rowspan,
        columnspan=columnspan,
        padx=padx,
        pady=pady,
        events=events,
        sticky=sticky,
        tooltip=tooltip,
        vscrollbar=vscrollbar,
        hscrollbar=hscrollbar,
        weightx=weightx,
        weighty=weighty,
        focus=focus,
        **kwargs,
    )

    self.kwargs = kwargs
    self._echo = echo
    self._stdout = stdout
    self._stderr = stderr

    # stores state for stdout and stderr redirection
    self._redirect = []
    self._redirect_id = {}

disable_redirect()

Disable redirecting stdout and stderr to the text box.

Source code in guitk/tk_text.py
327
328
329
330
def disable_redirect(self):
    """Disable redirecting stdout and stderr to the text box."""
    for r in self._redirect:
        r.disable_redirect()

enable_redirect()

Enable redirecting stdout and stderr to the text box.

Source code in guitk/tk_text.py
332
333
334
335
def enable_redirect(self):
    """Enable redirecting stdout and stderr to the text box."""
    for r in self._redirect:
        r.enable_redirect()

Menu bar manager that can be used to create a menu bar for a Window

Source code in guitk/menu.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
class MenuBar:
    """Menu bar manager that can be used to create a menu bar for a Window"""

    def __init__(
        self,
    ):
        """Create a new MenuBar.

        Examples:
            ```python
            import guitk as ui

            class MenuDemo(ui.Window):
                def config(self):
                    with ui.VLayout():
                        ui.Label("This window has menus!")

                    with ui.MenuBar():
                        with ui.Menu("File"):
                            ui.Command("Open...", shortcut="Ctrl+O")
                            with ui.SubMenu("Open Recent"):
                                ui.Command("File 1")
                                ui.Command("File 2")
                                ui.Command("File 3")
                            ui.MenuSeparator()
                            ui.Command("Save", key="File|Save", disabled=True)
                            ui.Command("Save As")
                        with ui.Menu("Edit", key="Edit", disabled=True):
                            ui.Command("Cut", shortcut="Ctrl+X")
                            ui.Command("Copy", shortcut="Ctrl+C")
                            ui.Command("Paste", shortcut="Ctrl+V")
            ```
        """
        self._index = 0
        self.window = None
        self._menu_list = []

        # get the caller's instance so we can set the layout
        caller_frame = currentframe().f_back
        with contextlib.suppress(IndexError, KeyError):
            first_arg = caller_frame.f_code.co_varnames[0]
            caller_instance = caller_frame.f_locals[first_arg]
            # determine if the caller is a Window
            # need to use repr() because we can't import Window here without causing a circular import
            if "guitk.window.Window" in repr(getmro(caller_instance.__class__)):
                self.window = caller_instance
                self.window.menu = self

    def _add_widget(self, widget: _BaseMenu):
        """Add a menu item to the end of the Menu"""
        self._menu_list.append(widget)

    def __enter__(self):
        push_parent(self)
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        pop_parent()
        return False

    def __iter__(self):
        self._index = 0
        return iter(self._menu_list)

    def __next__(self) -> Menu:
        if self._index >= len(self._menu_list):
            raise StopIteration
        value = self._menu_list[self._index]
        self._index += 1
        return value

__init__()

Create a new MenuBar.

Examples:

import guitk as ui

class MenuDemo(ui.Window):
    def config(self):
        with ui.VLayout():
            ui.Label("This window has menus!")

        with ui.MenuBar():
            with ui.Menu("File"):
                ui.Command("Open...", shortcut="Ctrl+O")
                with ui.SubMenu("Open Recent"):
                    ui.Command("File 1")
                    ui.Command("File 2")
                    ui.Command("File 3")
                ui.MenuSeparator()
                ui.Command("Save", key="File|Save", disabled=True)
                ui.Command("Save As")
            with ui.Menu("Edit", key="Edit", disabled=True):
                ui.Command("Cut", shortcut="Ctrl+X")
                ui.Command("Copy", shortcut="Ctrl+C")
                ui.Command("Paste", shortcut="Ctrl+V")
Source code in guitk/menu.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
def __init__(
    self,
):
    """Create a new MenuBar.

    Examples:
        ```python
        import guitk as ui

        class MenuDemo(ui.Window):
            def config(self):
                with ui.VLayout():
                    ui.Label("This window has menus!")

                with ui.MenuBar():
                    with ui.Menu("File"):
                        ui.Command("Open...", shortcut="Ctrl+O")
                        with ui.SubMenu("Open Recent"):
                            ui.Command("File 1")
                            ui.Command("File 2")
                            ui.Command("File 3")
                        ui.MenuSeparator()
                        ui.Command("Save", key="File|Save", disabled=True)
                        ui.Command("Save As")
                    with ui.Menu("Edit", key="Edit", disabled=True):
                        ui.Command("Cut", shortcut="Ctrl+X")
                        ui.Command("Copy", shortcut="Ctrl+C")
                        ui.Command("Paste", shortcut="Ctrl+V")
        ```
    """
    self._index = 0
    self.window = None
    self._menu_list = []

    # get the caller's instance so we can set the layout
    caller_frame = currentframe().f_back
    with contextlib.suppress(IndexError, KeyError):
        first_arg = caller_frame.f_code.co_varnames[0]
        caller_instance = caller_frame.f_locals[first_arg]
        # determine if the caller is a Window
        # need to use repr() because we can't import Window here without causing a circular import
        if "guitk.window.Window" in repr(getmro(caller_instance.__class__)):
            self.window = caller_instance
            self.window.menu = self

Bases: _BaseMenu

Source code in guitk/menu.py
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
class Menu(_BaseMenu):
    def __init__(
        self,
        label: str,
        underline: int | None = None,
        key: Hashable | None = None,
        disabled: bool = False,
    ) -> None:
        """Create a new Menu.

        Args:
            label (str): The label for the menu
            underline (int, optional): The index of the character to underline in the label. Defaults to None.
            key (Hashable, optional): The key to use to access the menu from parent Window.
                Defaults to  f"Menu:{label}" for top level menus and f"Menu:{parent_label|label...}" for submenus.
            disabled: Create menu in disabled state. Defaults to False.

        Note:
            If the menu is created within a MenuBar context manager, the menu will be added to the MenuBar.
            If the menu is created within a Menu context manager, the menu will be added to the parent Menu as a submenu.

        Examples:
            ```python
            import guitk as ui

            class MenuDemo(ui.Window):
                def config(self):
                    with ui.VLayout():
                        ui.Label("This window has menus!")

                    with ui.MenuBar():
                        with ui.Menu("File"):
                            ui.Command("Open...", shortcut="Ctrl+O")
                            with ui.SubMenu("Open Recent"):
                                ui.Command("File 1")
                                ui.Command("File 2")
                                ui.Command("File 3")
                            ui.MenuSeparator()
                            ui.Command("Save", key="File|Save", disabled=True)
                            ui.Command("Save As")
                        with ui.Menu("Edit", key="Edit", disabled=True):
                            ui.Command("Cut", shortcut="Ctrl+X")
                            ui.Command("Copy", shortcut="Ctrl+C")
                            ui.Command("Paste", shortcut="Ctrl+V")
            ```
        """
        super().__init__(label, disabled=disabled)
        self._menu = None
        self._underline = underline
        self.window = None
        self._index = 0
        self.key = key

    def _create_widget(self, parent: tk.Menu, window: Window, path: str | None = None):
        """Create the Menu widget and add it to the parent

        Args:
            parent: The parent widget
            window: The Window that owns this Menu
            path: The path to the parent widget, used only by subclasses
        """
        debug(
            f"Menu._create_widget: {self=} {self._label=} {parent=} {window=} {path=}"
        )
        self.window = window
        self._parent = parent
        menu = tk.Menu(parent)
        if self._underline is None:
            idx = self._label.find("&")
            if idx != -1:
                self._label = self._label.replace("&", "", 1)
                self._underline = idx
        parent.add_cascade(menu=menu, label=self._label, underline=self._underline)

        self._menu = menu
        self.key = self.key or path
        self.path = path or ""

        if self._disabled:
            self.disabled = True

    def _add_widget(self, widget):
        """Add a menu item to the end of the Menu"""
        self._menu_list.append(widget)

    def __enter__(self):
        push_parent(self)
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        pop_parent()
        return False

    def __iter__(self):
        self._index = 0
        return iter(self._menu_list)

    def __next__(self) -> Menu | Command:
        if self._index >= len(self._menu_list):
            raise StopIteration
        value = self._menu_list[self._index]
        self._index += 1
        return value

__init__(label, underline=None, key=None, disabled=False)

Create a new Menu.

Parameters:

Name Type Description Default
label str

The label for the menu

required
underline int

The index of the character to underline in the label. Defaults to None.

None
key Hashable

The key to use to access the menu from parent Window. Defaults to f"Menu:{label}" for top level menus and f"Menu:{parent_label|label...}" for submenus.

None
disabled bool

Create menu in disabled state. Defaults to False.

False
Note

If the menu is created within a MenuBar context manager, the menu will be added to the MenuBar. If the menu is created within a Menu context manager, the menu will be added to the parent Menu as a submenu.

Examples:

import guitk as ui

class MenuDemo(ui.Window):
    def config(self):
        with ui.VLayout():
            ui.Label("This window has menus!")

        with ui.MenuBar():
            with ui.Menu("File"):
                ui.Command("Open...", shortcut="Ctrl+O")
                with ui.SubMenu("Open Recent"):
                    ui.Command("File 1")
                    ui.Command("File 2")
                    ui.Command("File 3")
                ui.MenuSeparator()
                ui.Command("Save", key="File|Save", disabled=True)
                ui.Command("Save As")
            with ui.Menu("Edit", key="Edit", disabled=True):
                ui.Command("Cut", shortcut="Ctrl+X")
                ui.Command("Copy", shortcut="Ctrl+C")
                ui.Command("Paste", shortcut="Ctrl+V")
Source code in guitk/menu.py
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
def __init__(
    self,
    label: str,
    underline: int | None = None,
    key: Hashable | None = None,
    disabled: bool = False,
) -> None:
    """Create a new Menu.

    Args:
        label (str): The label for the menu
        underline (int, optional): The index of the character to underline in the label. Defaults to None.
        key (Hashable, optional): The key to use to access the menu from parent Window.
            Defaults to  f"Menu:{label}" for top level menus and f"Menu:{parent_label|label...}" for submenus.
        disabled: Create menu in disabled state. Defaults to False.

    Note:
        If the menu is created within a MenuBar context manager, the menu will be added to the MenuBar.
        If the menu is created within a Menu context manager, the menu will be added to the parent Menu as a submenu.

    Examples:
        ```python
        import guitk as ui

        class MenuDemo(ui.Window):
            def config(self):
                with ui.VLayout():
                    ui.Label("This window has menus!")

                with ui.MenuBar():
                    with ui.Menu("File"):
                        ui.Command("Open...", shortcut="Ctrl+O")
                        with ui.SubMenu("Open Recent"):
                            ui.Command("File 1")
                            ui.Command("File 2")
                            ui.Command("File 3")
                        ui.MenuSeparator()
                        ui.Command("Save", key="File|Save", disabled=True)
                        ui.Command("Save As")
                    with ui.Menu("Edit", key="Edit", disabled=True):
                        ui.Command("Cut", shortcut="Ctrl+X")
                        ui.Command("Copy", shortcut="Ctrl+C")
                        ui.Command("Paste", shortcut="Ctrl+V")
        ```
    """
    super().__init__(label, disabled=disabled)
    self._menu = None
    self._underline = underline
    self.window = None
    self._index = 0
    self.key = key

Command

Bases: Menu

Source code in guitk/menu.py
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
class Command(Menu):
    def __init__(
        self,
        label: str,
        shortcut: str = None,
        key: Hashable | None = None,
        command: CommandType | None = None,
        disabled: bool = False,
    ):
        """Create a new menu command

        Args:
            label (str): The label for the menu command
            shortcut (str, optional): The shortcut for the menu command
            key (Hashable, optional): Optional key for the menu command (defaults to the path to the menu command)
            command (CommandType, optional): The command to run when the menu command is selected
            disabled (bool): Create command in disabled state. Defaults to False.

        Note:
            Emits EventType.MenuCommand when command is selected or shortcut is pressed.

        Examples:
            ```python
            import guitk as ui

            class MenuDemo(ui.Window):
                def config(self):
                    with ui.VLayout():
                        ui.Label("This window has menus!")

                    with ui.MenuBar():
                        with ui.Menu("File"):
                            ui.Command("Open...", shortcut="Ctrl+O")
                            with ui.SubMenu("Open Recent"):
                                ui.Command("File 1")
                                ui.Command("File 2")
                                ui.Command("File 3")
                            ui.MenuSeparator()
                            ui.Command("Save", key="File|Save", disabled=True)
                            ui.Command("Save As")
                        with ui.Menu("Edit", key="Edit", disabled=True):
                            ui.Command("Cut", shortcut="Ctrl+X")
                            ui.Command("Copy", shortcut="Ctrl+C")
                            ui.Command("Paste", shortcut="Ctrl+V")
            ```
        """
        super().__init__(label, disabled=disabled)
        self.shortcut = shortcut
        self._parent = None
        self.key = key
        self._command = command

    def _create_widget(self, parent: tk.Menu, window: Window, path: str):
        """Create the Menu widget and add it to the parent

        Args:
            parent: The parent widget
            window: The Window that owns this Menu
            path: The path to the parent widget, used as the key for the command
        """
        debug(f"Command._create_widget: {self=} {parent=} {window=} {path=}")
        self._parent = parent
        self.window = window
        self.key = self.key or path
        self.path = path or ""

        parent.add_command(
            label=self._label,
            command=self.window._make_callback(
                Event(self, self.window, self.key, EventType.MenuCommand)
            ),
            accelerator=self.shortcut,
        )

        if self._command:
            self.window.bind_command(
                key=self.key, event_type=EventType.MenuCommand, command=self._command
            )

        if self._disabled:
            self.disabled = True

        key_binding = _map_key_binding_from_shortcut(self.shortcut)

        def _make_callback(event):
            def _callback(*arg):
                if self._self_or_ancestor_is_disabled():
                    # if self or any ancestor is disabled, ignore the shortcut event
                    return
                if arg:
                    event.event = arg[0]
                self.window._handle_event(event)

            return _callback

        window.window.bind_all(
            key_binding,
            _make_callback(Event(self, self.window, self.key, EventType.MenuCommand)),
        )

__init__(label, shortcut=None, key=None, command=None, disabled=False)

Create a new menu command

Parameters:

Name Type Description Default
label str

The label for the menu command

required
shortcut str

The shortcut for the menu command

None
key Hashable

Optional key for the menu command (defaults to the path to the menu command)

None
command CommandType

The command to run when the menu command is selected

None
disabled bool

Create command in disabled state. Defaults to False.

False
Note

Emits EventType.MenuCommand when command is selected or shortcut is pressed.

Examples:

import guitk as ui

class MenuDemo(ui.Window):
    def config(self):
        with ui.VLayout():
            ui.Label("This window has menus!")

        with ui.MenuBar():
            with ui.Menu("File"):
                ui.Command("Open...", shortcut="Ctrl+O")
                with ui.SubMenu("Open Recent"):
                    ui.Command("File 1")
                    ui.Command("File 2")
                    ui.Command("File 3")
                ui.MenuSeparator()
                ui.Command("Save", key="File|Save", disabled=True)
                ui.Command("Save As")
            with ui.Menu("Edit", key="Edit", disabled=True):
                ui.Command("Cut", shortcut="Ctrl+X")
                ui.Command("Copy", shortcut="Ctrl+C")
                ui.Command("Paste", shortcut="Ctrl+V")
Source code in guitk/menu.py
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
def __init__(
    self,
    label: str,
    shortcut: str = None,
    key: Hashable | None = None,
    command: CommandType | None = None,
    disabled: bool = False,
):
    """Create a new menu command

    Args:
        label (str): The label for the menu command
        shortcut (str, optional): The shortcut for the menu command
        key (Hashable, optional): Optional key for the menu command (defaults to the path to the menu command)
        command (CommandType, optional): The command to run when the menu command is selected
        disabled (bool): Create command in disabled state. Defaults to False.

    Note:
        Emits EventType.MenuCommand when command is selected or shortcut is pressed.

    Examples:
        ```python
        import guitk as ui

        class MenuDemo(ui.Window):
            def config(self):
                with ui.VLayout():
                    ui.Label("This window has menus!")

                with ui.MenuBar():
                    with ui.Menu("File"):
                        ui.Command("Open...", shortcut="Ctrl+O")
                        with ui.SubMenu("Open Recent"):
                            ui.Command("File 1")
                            ui.Command("File 2")
                            ui.Command("File 3")
                        ui.MenuSeparator()
                        ui.Command("Save", key="File|Save", disabled=True)
                        ui.Command("Save As")
                    with ui.Menu("Edit", key="Edit", disabled=True):
                        ui.Command("Cut", shortcut="Ctrl+X")
                        ui.Command("Copy", shortcut="Ctrl+C")
                        ui.Command("Paste", shortcut="Ctrl+V")
        ```
    """
    super().__init__(label, disabled=disabled)
    self.shortcut = shortcut
    self._parent = None
    self.key = key
    self._command = command

Bases: Menu

Separator that adds a dividing line between menu items.

Examples:

import guitk as ui

class MenuDemo(ui.Window):
    def config(self):
        with ui.VLayout():
            ui.Label("This window has menus!")

        with ui.MenuBar():
            with ui.Menu("File"):
                ui.Command("Open...", shortcut="Ctrl+O")
                with ui.SubMenu("Open Recent"):
                    ui.Command("File 1")
                    ui.Command("File 2")
                    ui.Command("File 3")
                ui.MenuSeparator()
                ui.Command("Save", key="File|Save", disabled=True)
                ui.Command("Save As")
            with ui.Menu("Edit", key="Edit", disabled=True):
                ui.Command("Cut", shortcut="Ctrl+X")
                ui.Command("Copy", shortcut="Ctrl+C")
                ui.Command("Paste", shortcut="Ctrl+V")
Source code in guitk/menu.py
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
class MenuSeparator(Menu):
    """Separator that adds a dividing line between menu items.

    Examples:
        ```python
        import guitk as ui

        class MenuDemo(ui.Window):
            def config(self):
                with ui.VLayout():
                    ui.Label("This window has menus!")

                with ui.MenuBar():
                    with ui.Menu("File"):
                        ui.Command("Open...", shortcut="Ctrl+O")
                        with ui.SubMenu("Open Recent"):
                            ui.Command("File 1")
                            ui.Command("File 2")
                            ui.Command("File 3")
                        ui.MenuSeparator()
                        ui.Command("Save", key="File|Save", disabled=True)
                        ui.Command("Save As")
                    with ui.Menu("Edit", key="Edit", disabled=True):
                        ui.Command("Cut", shortcut="Ctrl+X")
                        ui.Command("Copy", shortcut="Ctrl+C")
                        ui.Command("Paste", shortcut="Ctrl+V")
        ```

    """

    def __init__(self) -> None:
        """Create a new MenuSeparator"""
        super().__init__("")

    def _create_widget(self, parent: tk.Menu, window: Window, path: str | None = None):
        """Create the Separator widget and add it to the parent

        Args:
            parent: The parent widget
            window: The Window that owns this Menu
            path: The path to the parent widget, used as the key for the command
        """
        debug(f"MenuSeparator._create_widget: {self=} {parent=} {window=} {path=}")
        self._parent = parent
        self.window = window
        parent.add_separator()
        self.key = f"{path}separator({id(self)})"
        self.path = path or ""

__init__()

Create a new MenuSeparator

Source code in guitk/menu.py
359
360
361
def __init__(self) -> None:
    """Create a new MenuSeparator"""
    super().__init__("")