Skip to main content

tk-uia

tests License: MIT Ruff

Make Tkinter applications fully accessible to Windows screen readers and UI Automation: named, correctly typed, and activatable.

Tk 8.6 exposes widgets to Windows accessibility with no names and mostly wrong control types: buttons are unnamed, labels read as images, and every themed ttk widget is an anonymous pane. tk_uia.enable(root) fixes both halves. Each widget is annotated through MSAA for legacy clients, and answers UI Automation for itself: Invoke genuinely presses, Value genuinely types, Toggle, SelectionItem and RangeValue genuinely act, and names and states are read live from the widget at the moment a client asks. Screen readers such as NVDA, and UIA tools such as Inspect.exe or pytest-uia, see controls they can both read and operate. No runtime dependencies, no C extension, no visible change to the window.

Install

pip install tk-uia

Windows only. On other platforms enable() returns UNSUPPORTED and does nothing, so cross-platform code can call it unconditionally.

Usage

import tkinter as tk
import tk_uia

root = tk.Tk()
root.title("Tasks")
tk.Label(root, text="Task list").pack()
tk.Button(root, text="New Task", command=create).pack()

tk_uia.enable(root)
root.mainloop()

enable() comes first: every other call (set_acc_name, label_for, the bind_* family) refuses until it has run.

Widget Bare Tk After enable()
tk.Button(text="New Task") ButtonControl, no name, Invoke does nothing ButtonControl, Name='New Task', Invoke presses it
tk.Label(text="Task list") ImageControl, no name TextControl, name read live
tk.Checkbutton(text="Done") ButtonControl, no name CheckBoxControl, Toggle works, live ToggleState
tk.Entry(textvariable=var) PaneControl, no ValuePattern EditControl, SetValue types into it
ttk.Button(text="Save") anonymous PaneControl ButtonControl, named, Invoke presses it
tk.Scale(from_=0, to=10) PaneControl SliderControl, RangeValue moves it

Measured from a separate process. COVERAGE.md has the table for every widget class in both toolkits. COOKBOOK.md builds a real form end to end.

Features

  • One call covers the whole application, including windows opened later.
  • Working patterns per class: Invoke for buttons, Toggle for checkbuttons, SelectionItem for radiobuttons and notebook tabs, Value for entries, spinboxes, comboboxes and Text, RangeValue for scales and progressbars.
  • Names, values, enabled state, help and description are pulled live at the moment a client asks; name and value changes are raised as UIA property-changed events.
  • Names inferred from -text, correct control types for classic tk and ttk.
  • A declared textvariable is followed automatically: the name or value stays current with no further code.
  • label_for(label, entry) records which caption names which field. infer_names_from_layout(root) retrofits an existing dialog in one call and reports every name it chose.
  • describe(root) returns an audit you can print(): what a client gets and what is missing, with a reason and a fix per widget. Usable as data for CI gating.
  • Notebook tabs become real tab controls a client can switch without a click.
  • annotate_only(root) keeps the previous annotation-only behaviour, and leave_to_the_proxy(widget) opts a single widget out.
  • Detects Tk 9.1's native accessibility (TIP 733) and stands down.

Limitations

  • In-process only. You can make your own application accessible, not someone else's.
  • Listbox rows and Treeview items are not exposed. Notebook tabs are.
  • A combobox has no ExpandCollapse yet, so a client cannot open its dropdown; choosing goes through ValuePattern.SetValue, which on a readonly combobox takes exactly the values a user could pick and fires the same <<ComboboxSelected>> a dropdown choice would.
  • infer_names_from_layout is a guess by convention: rows are frames, or grid rows within a frame, read across their columns. It returns every name it chose; read the guess before shipping it.
  • A widget left to the MSAA proxy advertises an InvokePattern that does nothing; that is the proxy's own behaviour, and describe() says which widgets it applies to.
  • Verified against the UI Automation tree, which is what screen readers consume. Not yet verified against NVDA speech output; that is what 1.0 means on the roadmap.

Documentation

COOKBOOK.md Your first accessible form, in ten minutes.
docs/GUIDE.md Full API, how it works, every caveat and measurement.
COVERAGE.md Every widget class, measured bare and after enable().
ROADMAP.md What is next and what is out of scope.
CHANGELOG.md Release history.

License

MIT

Release files for tk-uia 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tk-uia 0.7.0
File Size Uploaded
tk_uia-0.7.0.tar.gz 177.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tk-uia 0.7.0
File Interpreter ABI Platform
tk_uia-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 234.6 kB

Release files / tk_uia-0.7.0.tar.gz

Download URL tk_uia-0.7.0.tar.gz
Size 177.4 kB
Tags Source
SHA-256 checksum
How to use checksums
83561fbde6a6409d072a886a18a07655aa4f714ffc9656b3aea9675d30f74a04
BLAKE2b-256 checksum
How to use checksums
404556c7e2e8c5d3a8d0516cda19ed5ac2f0d5285213fceaaa2df49ff3f67fbe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 28, 2026.

Transparency log

Release files / tk_uia-0.7.0-py3-none-any.whl

Download URL tk_uia-0.7.0-py3-none-any.whl
Size 57.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c5db5cca7012f17304e2cccf3a645050d4ecc16a2721790007c5597404769291
BLAKE2b-256 checksum
How to use checksums
97dd6222b98659011b82f1baf3e0b99fa3746c0d9f62d7a1305be9b7d119b490
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 28, 2026.

Transparency log

Release history Release notifications | RSS feed

0.8.0

2 release files

This release

0.7.0 This release

2 release files

0.6.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page