widget-creation
Skill921 starsChanged 4 months agoMITView on GitHub
Use when: creating new TTkWidget subclasses with proper structure, signals, slots, and documentation
In this repository4 other files it gives its agents.
- pyTermTk-agentsAGENTS.md
- .github/copilot-instructions.mdCopilot instructions
- review-branch-or-prSkill
- test-first-fixSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 0 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 185
Add to demo/showcase/ or tutorial/examples/ if creating showcase:
- Very specific: line 219
Keep signal entries in __slots__ and type-annotate them there
- Very specific: line 238
All non-signal slot names must start with _.
- Very specific: line 240
Add a class-level type annotation for each slot entry immediately below __slots__.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Widget Creation Skill
Overview
This skill scaffolds new pyTermTk widgets following project patterns:
- Proper class structure with
__slots__ - Signal definitions with type hints
- Event handlers with correct return semantics
- Sphinx documentation with ASCII art
- Test file structure
- Example/demo integration
When to Use
- Building new interactive widgets (button, input, selector variants)
- Creating container widgets (custom layouts, panels)
- Adding display widgets (custom text renderers, charts)
File Structure
1. Widget File
Location: libs/pyTermTk/TermTk/TTkWidgets/ttk_<widget_name>.py
Template:
"""
Module: TTkMyWidget
Implements a custom widget for [purpose]
"""
from TermTk import TTkWidget, TTkColor, pyTTkSignal, pyTTkSlot
class TTkMyWidget(TTkWidget):
'''TTkMyWidget: [One-line description]
[Longer description of purpose and behavior]
(`demo <https://ceccopierangiolieugenio.github.io/pyTermTk-Docs/sandbox/...>`__)
::
[ASCII art showing visual representation]
[Multiple lines if needed]
.. code:: python
import TermTk as ttk
root = ttk.TTk()
widget = ttk.TTkMyWidget(parent=root)
root.mainloop()
'''
# Performance: always use __slots__
__slots__ = (
'_privateVar',
'_anotherVar',
'stateChanged',
)
_privateVar: int
_anotherVar: int
stateChanged: pyTTkSignal
'''
Emitted when widget state changes.
:param value: new state value
:type value: [type]
'''
# Class-level styling
classStyle = {
'default': {'color': TTkColor.fg("#dddd88"), 'borderColor': TTkColor.RST},
'hover': {'color': TTkColor.fg("#ffffff"), 'borderColor': TTkColor.BOLD},
'focus': {'borderColor': TTkColor.fg("#ffff00")},
'disabled': {'color': TTkColor.fg('#888888')}
}
def __init__(self, **kwargs):
'''Initialize the widget.
:param parent: parent widget
:type parent: TTkWidget
[Other parameters as needed]
'''
# Instantiate signals in __init__ (do not instantiate at class level)
self.stateChanged = pyTTkSignal(int)
# Initialize private variables
self._privateVar = 0 # Replace with appropriate default for your widget
# Call parent with merged kwargs and default size
super().__init__(**kwargs|{'size': (10, 3)}) # Replace with appropriate default dimensions
# Property getters/setters
def getValue(self) -> int:
'''Get the current value.
:return: current value
:rtype: int
'''
return self._privateVar
def setValue(self, value: int) -> None:
'''Set the value.
:param value: new value
:type value: int
'''
if self._privateVar != value:
self._privateVar = value
self.stateChanged.emit(value)
self.update()
# Return True when this widget fully processes the event; otherwise return False to let parent widgets handle it.
def keyEvent(self, evt) -> bool:
'''Handle keyboard events.'''
if evt.key == 'Enter':
self.stateChanged.emit(self._privateVar)
return True
return False
def mousePressEvent(self, evt) -> bool:
'''Handle mouse press events.'''
# Handle click, return True if consumed
return False
def paintEvent(self) -> None:
'''Render the widget.'''
# Use currentStyle() for theme-aware colors
canvas = self.canvas
style = self.currentStyle()
# Draw widget content
canvas.drawText(pos=(0, 0), text="MyWidget")
__all__ = ['TTkMyWidget']2. Test File
Location: tests/pytest/widgets/<widget_name>/test_<widget_name>.py
Template:
import pytest
from TermTk import TTkMyWidget
class TestTTkMyWidget:
'''Test suite for TTkMyWidget'''
def test_initialization(self):
"""Widget initializes with defaults"""
widget = TTkMyWidget()
assert widget.getValue() == 0 # Or expected default
def test_signal_emission(self):
"""Signal emits when state changes"""
widget = TTkMyWidget()
emitted = []
widget.stateChanged.connect(lambda val: emitted.append(val))
widget.setValue(42)
assert emitted == [42]
def test_key_event_handling(self):
"""Key events handled correctly"""
widget = TTkMyWidget()
from TermTk import TTkKeyEvent
evt = TTkKeyEvent(key='Enter')
result = widget.keyEvent(evt)
assert result == True # Event was handled
def test_disabled_state(self):
"""Widget respects disabled state"""
widget = TTkMyWidget()
widget.setDisabled(True)
# Verify widget doesn't respond to events, etc.3. Example/Demo
Add to demo/showcase/ or tutorial/examples/ if creating showcase:
"""
Example: TTkMyWidget
Demonstrates the TTkMyWidget in action.
"""
import TermTk as ttk
def main():
root = ttk.TTk()
# Create and configure widget
widget = ttk.TTkMyWidget(parent=root)
widget.setValue(10)
# Connect signal
@ttk.pyTTkSlot(int)
def on_state_changed(value):
print(f"State changed to: {value}")
widget.stateChanged.connect(on_state_changed)
root.mainloop()
if __name__ == '__main__':
main()Key Patterns to Follow
Signals
- Keep signal entries in
__slots__and type-annotate them there - Instantiate signals in
__init__with specific type:pyTTkSignal(int)notpyTTkSignal() - Emit with actual value:
self.stateChanged.emit(value)
slots
__slots__ = (
'_variable1',
'_variable2',
'valueChanged',
# Always use slots for memory efficiency
)
_variable1: int
_variable2: int
valueChanged: pyTTkSignalRules:
- All non-signal slot names must start with
_. - Public (non-underscore) slot names are allowed only for exposed signals.
- Add a class-level type annotation for each slot entry immediately below
__slots__.
Class Styling
classStyle = {
'default': {...},
'hover': {...},
'focus': {...},
'disabled': {...}
}Event Return Values
- Return
Trueif event fully handled (don't propagate) - Return
Falseto let event propagate up widget tree
Documentation
- ASCII art for visual widgets
- Demo/sandbox links
- Runnable code examples
- Sphinx cross-references:
:py:class:,:py:meth:
Checklist
File and Class Structure
- File location:
libs/pyTermTk/TermTk/TTkWidgets/ttk_*.py - Inherits from
TTkWidgetorTTkContainer __slots__defined- Non-signal slot names use leading
_ - Public slot names are signals only
- Every slot entry has a class-level type annotation
__all__export defined- Register the widget export in
libs/pyTermTk/TermTk/TTkWidgets/__init__.pywithfrom .ttk_<widget_name> import TTkMyWidget
Signals and Events
- Signals with type hints
- Signals initialized in
__init__ - Event methods return bool
Documentation and Examples
- Sphinx docstring with ASCII art
- Example added to demo or tutorial
Testing and Quality
- Test file created
- Tests cover initialization, signals, events, edge cases
- Flake8 passes
Common Mistakes to Avoid
- ❌ Signals instantiated at class level instead of
__init__ - ❌ Event handlers don't return bool (should always return True/False)
- ❌ Missing
__slots__(memory waste) - ❌ Hardcoded colors instead of using theme via
currentStyle() - ❌ Tests that only check implementation, not behavior
- ❌ No documentation or examples
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

