Skip to main content

Declarative UI library built on tkinter

Project description

dkinter

Declarative UI library built on top of Python's tkinter. Describe your UI as a tree of nested descriptor objects instead of calling imperative widget methods.

from dkinter import App, Label, Button, State, PackLayout, PackLayoutItem

count = State(0)

App(
    title="Counter",
    width=300, height=150,
    layout=PackLayout(items=[
        PackLayoutItem(widget=Label(text=count, font=("Arial", 24)), pady=20),
        PackLayoutItem(widget=Button(text="Click me", on_click=lambda: count.set(count.get() + 1))),
    ])
).run()

Installation

pip install dkinter

Requires Python 3.10+ and tkinter (included with standard Python on Windows and macOS).


Core Concepts

State

State[T] is an observable value. Bind it directly to any widget property — the UI updates automatically when the value changes.

name = State("World")
label = Label(text=name)           # updates whenever name changes
name.set("dkinter")                # label text updates immediately

show = State(True)
frame = Frame(visible=show)        # hide/show the entire frame

title = State.derived(lambda: f"Hello, {name.get()}!")  # computed from other states

Ref

Ref[T] gives you a handle to a live widget after the app is built.

from dkinter import Ref
from dkinter.live import LiveEntry

entry_ref: Ref[LiveEntry] = Ref()

App(layout=PackLayout(items=[
    PackLayoutItem(widget=Entry(ref=entry_ref)),
    PackLayoutItem(widget=Button(text="Get", on_click=lambda: print(entry_ref.current.value))),
])).run()

Layouts

Layout Description
PackLayout Stack widgets top-to-bottom or side-by-side
GridLayout Place widgets in rows and columns
PlaceLayout Absolute or relative positioning
GridLayout(
    column_weights={0: 1, 1: 2},
    items=[
        GridLayoutItem(widget=Label(text="Name:"), row=0, column=0),
        GridLayoutItem(widget=Entry(), row=0, column=1, sticky="ew"),
    ]
)

Widgets

tk widgets (default)

from dkinter import Label, Button, Entry, Text, Frame, LabelFrame
from dkinter import Checkbutton, Radiobutton, Listbox, Spinner, Canvas, Scrollbar
Widget Key params
Label text, font, fg, bg
Button text, on_click, font, fg, bg
Entry on_change, font, fg, bg
Text width, height, on_change, font, fg, bg
Frame layout, bg
LabelFrame text, layout, font, fg, bg
Checkbutton text, on_change, check_bg, font, fg, bg
Radiobutton text, value, check_bg, font, fg, bg
Listbox items, select_mode, on_select, height
Spinner values or from_/to/increment, on_change, wrap
Canvas width, height, on_click, on_mouse_move
Scrollbar orient, target

ttk widgets (themed)

from dkinter.widgets.ttk import Label, Button, Entry, Checkbutton
from dkinter.widgets.ttk import Combobox, Progressbar, Notebook, Treeview, Menubutton
Widget Key params
Label text, font, fg, bg
Button text, on_click, font, fg, bg
Entry on_change, font, fg, bg
Checkbutton text, value, on_change, font, fg, bg
Combobox values, selected, state, on_select
Progressbar value, maximum, mode, orient
Notebook tabs, on_change
Treeview columns, rows, show, on_select
Menubutton text, menu, direction, font, fg, bg

Note: ttk font/fg/bg styling requires a non-native theme on Windows. Add theme="clam" (or "alt") to your App to enable full color control.


App

App(
    title="My App",
    width=800,
    height=600,
    resizable=True,
    theme="clam",           # ttk theme: clam, alt, default, classic
    layout=...,
    menu=MenuBar(...),
    on_close=handle_close,
    on_key=handle_key,
    on_resize=handle_resize,
).run()

Menus

from dkinter import MenuBar, Menu, MenuCommand, MenuSeparator

App(
    menu=MenuBar(menus=[
        Menu(label="File", items=[
            MenuCommand(label="New",  on_click=on_new),
            MenuCommand(label="Open", on_click=on_open),
            MenuSeparator(),
            MenuCommand(label="Exit", on_click=on_exit),
        ]),
    ]),
    ...
)

Dialogs

from dkinter import (
    open_file, open_files, save_file, open_directory,
    show_info, show_warning, show_error,
    ask_yes_no, ask_ok_cancel, ask_retry_cancel,
    pick_color,
)

path  = open_file(filetypes=[("Text files", "*.txt")])
color = pick_color(initial="#ffffff")
ok    = ask_yes_no(title="Confirm", message="Are you sure?")

Canvas

from dkinter import Ref
from dkinter.live import LiveCanvas

canvas_ref: Ref[LiveCanvas] = Ref()

# after app is built:
c = canvas_ref.current
rect_id = c.draw_rect(10, 10, 100, 60, fill="steelblue")
c.make_draggable(rect_id)
c.make_hoverable(rect_id, hover={"fill": "red"}, normal={"fill": "steelblue"})

ttk Checkbutton (two-way binding)

from dkinter.widgets.ttk import Checkbutton
from dkinter import State

checked = State(False)
Checkbutton(text="Enable feature", value=checked, on_change=lambda v: print(v))
# checked.set(True) → checks the box; user click → updates checked

ttk Menubutton

from dkinter.widgets.ttk import Menubutton
from dkinter.menu import Menu, MenuCommand, MenuSeparator

Menubutton(
    text="File",
    font=("Arial", 10),
    fg="#003399",
    direction="below",      # above | below | left | right | flush
    menu=Menu(label="File", items=[
        MenuCommand(label="New",  on_click=on_new),
        MenuSeparator(),
        MenuCommand(label="Exit", on_click=on_exit),
    ]),
)

Widget Common Params

All widgets inherit these from the base Widget class:

Param Type Description
visible bool | State[bool] Show/hide the widget
ref Ref Access the live widget after build
font tuple | str e.g. ("Arial", 12, "bold")
fg str Foreground/text color
bg str Background color
context_menu Menu Right-click popup menu
on_click Callable Left mouse button
on_right_click Callable Right mouse button
on_double_click Callable Double click
on_enter Callable Mouse enters widget
on_leave Callable Mouse leaves widget
on_focus_in Callable Widget gains focus
on_focus_out Callable Widget loses focus
on_key Callable[[str], None] Key pressed while focused

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dkinter-0.1.0-py3-none-any.whl (30.6 kB view details)

Uploaded Python 3

File details

Details for the file dkinter-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: dkinter-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for dkinter-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 202f73223d0479cc41af14f97091f2888bef47dd30a14f5e57ee6b15a11221c1
MD5 76b65999012cb7d782f5bcbb4c61c759
BLAKE2b-256 0cb0c98485407f62326b466bb5282eb686f951b5e2c8f1a5863b2bad9bf8d477

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page