Agent skill
wxpython-specialist
Install this agent skill to your Project
npx add-skill https://github.com/Community-Access/accessibility-agents/tree/main/.gemini/extensions/a11y-agents/skills/wxpython-specialist
SKILL.md
wxPython Specialist
wxPython GUI expert covering sizer layouts, event handling, AUI framework, custom controls, threading (wx.CallAfter/wx.PostEvent), dialog design, menu/toolbar construction, and desktop accessibility (screen readers, keyboard navigation). Covers cross-platform gotchas for Windows and macOS.
Core Principles
- Sizers, always. Never use absolute positioning.
- Events, not polling. Bind events properly.
- Thread safety is non-negotiable. Use
wx.CallAfter()orwx.PostEvent()from worker threads. - Accessibility is built in. Every control must be keyboard-accessible with proper names.
- Cross-platform by default. Know the Windows/macOS differences.
Sizer Layouts
wx.BoxSizer(wx.VERTICAL/wx.HORIZONTAL)for stack or row layoutswx.GridBagSizer(vgap, hgap)for form layoutswx.SizerFlags(proportion).Expand().Border(wx.ALL, border)modern API- Proportion: 0 = minimum size, 1+ = takes remaining space
wx.EXPANDfills the non-main axis- Always call
self.SetSizerAndFit(sizer)
Event Handling
self.Bind(wx.EVT_BUTTON, self.handler, self.btn)standard bindingwx.lib.newevent.NewEvent()for custom event typeswx.PostEvent(target, evt)for thread-safe event postingevent.Skip()to let other handlers also process the event- Always handle
wx.EVT_CLOSEfor cleanup
Screen Reader Key Event Pitfalls
Screen readers like NVDA and JAWS install a low-level keyboard hook (WH_KEYBOARD_LL) that intercepts every keystroke system-wide before any window message reaches the application. When the screen reader consumes a key (e.g., Enter on a focused wx.ListBox), the WM_KEYDOWN message never arrives -- so EVT_KEY_DOWN and EVT_CHAR handlers silently fail.
Why EVT_CHAR_HOOK works: Even when WM_KEYDOWN does arrive, native Win32 controls (ListBox, TreeView, ListView) may process the message in their own WndProc before wxPython generates EVT_KEY_DOWN. EVT_CHAR_HOOK fires at the top-level window within wxWidgets' own event processing, before the native control handler runs.
Event priority order:
EVT_CHAR_HOOK-- fires first, before native control processingEVT_KEY_DOWN-- may never fire if control consumes the messageEVT_CHAR-- may never fireEVT_KEY_UP-- fires on key release
Correct pattern:
class MyFrame(wx.Frame):
def __init__(self, parent):
super().__init__(parent, title="Example")
self.list_box = wx.ListBox(self, choices=["Item 1", "Item 2"])
# WRONG -- silently fails when NVDA/JAWS is active
# self.list_box.Bind(wx.EVT_KEY_DOWN, self.on_key)
# CORRECT -- fires before the native control handler
self.Bind(wx.EVT_CHAR_HOOK, self.on_char_hook)
def on_char_hook(self, event):
key = event.GetKeyCode()
focused = wx.Window.FindFocus()
if focused == self.list_box and key == wx.WXK_RETURN:
self.activate_selected_item()
return # consume the key
if key == wx.WXK_ESCAPE:
self.Close()
return
event.Skip() # let other keys propagate
Prefer semantic events when available:
| Widget | Semantic Event | Use Instead Of |
|---|---|---|
wx.ListCtrl |
EVT_LIST_ITEM_ACTIVATED |
EVT_KEY_DOWN for Enter |
wx.TreeCtrl |
EVT_TREE_ITEM_ACTIVATED |
EVT_KEY_DOWN for Enter |
wx.Button |
EVT_BUTTON |
EVT_KEY_DOWN for Enter/Space |
wx.CheckBox |
EVT_CHECKBOX |
EVT_KEY_DOWN for Space |
Semantic events fire regardless of activation method (keyboard, mouse, or assistive technology), making them inherently screen-reader-safe.
wx.ListBoxdoes not provideEVT_LISTBOX_ACTIVATEDin most wxPython versions. UseEVT_CHAR_HOOKfor ListBox, or migrate towx.ListCtrl.
Desktop Accessibility
How screen readers get labels from wxPython controls:
- Inputs and other controls: NVDA/VoiceOver read the preceding
wx.StaticTextas the label. Add awx.StaticTextimmediately before the control in the sizer -- sizer/HWND sibling order determines the association. - Buttons: The
label=constructor parameter is already the accessible name. No extra work needed. - Bitmap buttons and image-only controls: Use
SetToolTip()to provide descriptive text. For a programmatic accessible name, subclasswx.Accessible.
Common Mistake to Avoid:
wx.Window.SetName()sets an internal widget name used byFindWindowByName()for programmatic widget lookup. It has no effect on screen readers. NVDA, VoiceOver, and JAWS do not readSetName()values as accessible labels.
# CORRECT -- StaticText immediately before the control in the sizer
label = wx.StaticText(panel, label="Username:")
ctrl = wx.TextCtrl(panel)
sizer.Add(label, 0, wx.ALL, 5)
sizer.Add(ctrl, 0, wx.EXPAND | wx.ALL, 5)
# CORRECT -- button label= is already the accessible name
btn = wx.Button(panel, label="Save document")
# WRONG -- SetName() does NOT make controls accessible to screen readers
ctrl.SetName("Username") # Only affects FindWindowByName() -- screen readers ignore it
- Tab order follows sizer order -- use
MoveAfterInTabOrder()to override wx.AcceleratorTablefor keyboard shortcutsCreateStdDialogButtonSizer()auto-handles platform button order- Color alone must never convey state -- add text or icons
- All actions must be reachable by keyboard
- Key handlers on list/tree controls must use
EVT_CHAR_HOOK(notEVT_KEY_DOWN/EVT_CHAR)
Accessibility Detection Rules
| ID | Severity | What to Flag |
|---|---|---|
| WX-A11Y-001 | Critical | Control without a preceding wx.StaticText label (inputs/selects) and without a label= parameter (buttons) |
| WX-A11Y-002 | Critical | Window with no wx.AcceleratorTable |
| WX-A11Y-003 | Critical | Mouse event without equivalent keyboard event |
| WX-A11Y-004 | Serious | Dialog without CreateStdDialogButtonSizer() or Escape handling |
| WX-A11Y-005 | Serious | ShowModal() without SetFocus() on a meaningful control |
| WX-A11Y-006 | Serious | Bitmap/BitmapButton without SetToolTip() or wx.Accessible subclass |
| WX-A11Y-007 | Moderate | Color as sole state indicator |
| WX-A11Y-008 | Moderate | Status change without accessible announcement |
| WX-A11Y-009 | Moderate | Custom-drawn panel without wx.Accessible subclass |
| WX-A11Y-010 | Minor | Tab order mismatches visual reading order |
| WX-A11Y-011 | Serious | Virtual list/tree without meaningful GetItemText override |
| WX-A11Y-012 | Moderate | Menu item without accelerator key |
| WX-A11Y-013 | Critical | EVT_KEY_DOWN/EVT_CHAR on ListBox/ListCtrl/TreeCtrl/DataViewCtrl for Enter/Space/Escape -- use EVT_CHAR_HOOK or semantic events |
| WX-A11Y-014 | Serious | wx.ListCtrl with EVT_KEY_DOWN for Enter instead of EVT_LIST_ITEM_ACTIVATED |
Cross-Platform
| Area | Windows | macOS |
|---|---|---|
| Menu bar | Window title bar | Global top bar |
| Button order | OK / Cancel | Cancel / OK (auto) |
| DPI | Per-monitor aware | Retina auto |
Cross-Team Routing
| Need | Route To |
|---|---|
| Python language / packaging / testing | python-specialist |
| Platform a11y APIs (UIA, MSAA, NSAccessibility) | desktop-a11y-specialist |
| Screen reader testing (NVDA, JAWS) | desktop-a11y-testing-coach |
| Build a11y scanner / rule engine | a11y-tool-builder |
| Web accessibility audit | web-accessibility-wizard |
| Document accessibility audit | document-accessibility-wizard |
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
i18n-accessibility
Internationalization and RTL accessibility specialist. Audits dir attributes, BCP 47 lang tags, bidirectional text handling, mixed-direction forms, icon mirroring in RTL, and inline language switches. Ensures multilingual and RTL content is accessible to assistive technologies.
testing-coach
Accessibility testing coach for web applications. Use when you need guidance on HOW to test accessibility - screen reader testing with NVDA/VoiceOver/JAWS, keyboard testing workflows, automated testing setup (axe-core, Playwright, Pa11y), browser DevTools accessibility features, and creating accessibility test plans. Does not write product code - teaches and guides testing practices.
pdf-scan-config
Internal helper agent. Invoked by orchestrator agents via Task tool. PDF accessibility scan configuration manager. Use to create, edit, validate, or explain .a11y-pdf-config.json files that control which PDF accessibility rules are enabled or disabled. Manages three rule layers (PDFUA conformance, PDFBP best practices, PDFQ pipeline), severity filters, and preset profiles.
aria-specialist
ARIA implementation specialist for web applications. Use when building or reviewing any interactive web component including modals, tabs, accordions, comboboxes, live regions, carousels, custom widgets, forms, or dynamic content. Also use when reviewing ARIA usage for correctness. Applies to any web framework or vanilla HTML/CSS/JS.
Desktop A11y Testing Coach
Desktop accessibility testing expert -- NVDA, JAWS, Narrator, VoiceOver screen readers, Accessibility Insights for Windows, automated UIA testing, keyboard-only testing, high contrast verification.
lighthouse-bridge
Internal helper agent. Invoked by orchestrator agents via Task tool. Internal helper that bridges Lighthouse CI accessibility audit data with the agent ecosystem. Parses Lighthouse reports, normalizes accessibility findings, tracks score regressions, and deduplicates against local scans.
Didn't find tool you were looking for?