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

fg, bg, and font also accept State for live styling changes:

color = State("#cc0000")
font  = State(("Arial", 11))

Label(text="Hello", fg=color, font=font)
Button(text="Go", bg=color, fg=State("white"))

color.set("#0055cc")   # all bound widgets update instantly
font.set(("Arial", 14, "bold"))

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, Frame
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
Frame layout, bg, padding
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()

Toplevel

Secondary windows opened on demand. Supports modal (blocks main window) and non-modal modes.

from dkinter import Toplevel

dialog = Toplevel(
    title="Settings",
    width=400,
    height=300,
    modal=True,
    on_close=lambda: print("closed"),
    layout=PackLayout(items=[
        PackLayoutItem(widget=Label(text="Hello from dialog")),
        PackLayoutItem(widget=Button(text="Close", on_click=lambda: dialog.close())),
    ]),
)

Button(text="Open", on_click=dialog.open)
Method / Property Description
dialog.open() Open the window (raises it if already open)
dialog.close() Close the window programmatically
dialog.is_open bool — whether the window is currently open

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 | State e.g. ("Arial", 12, "bold") — supports State
fg str | State[str] Foreground/text color — supports State
bg str | State[str] Background color — supports State
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.2.0-py3-none-any.whl (33.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: dkinter-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 33.5 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d5a6bbcd2e11a5899c32574724f0242ae71eb51bd6a1f75660aefd871c9c1a37
MD5 5e712557a40a1f8f154ba5b8efabd0e4
BLAKE2b-256 5fc03b18510dd4ed7d5d99b4fe3b17c8e4ba0d2e982b0b64c14f7e753adc42b0

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