Python Terminal Toolkit for creating sophisticated text-based user interfaces with Qt-like API and full widget support
—
Signal-slot communication system for event handling and inter-widget communication patterns.
pyTTkSignal provides the signal mechanism for event communication between objects.
class pyTTkSignal:
def __init__(self, *types):
"""
Initialize a signal.
Parameters:
- types: Type hints for signal parameters (optional)
"""
def connect(self, slot):
"""
Connect a slot function to this signal.
Parameters:
- slot: Function or method to call when signal is emitted
"""
def disconnect(self, slot=None):
"""
Disconnect a slot from this signal.
Parameters:
- slot: Specific slot to disconnect, or None to disconnect all
"""
def emit(self, *args):
"""
Emit the signal with optional arguments.
Parameters:
- args: Arguments to pass to connected slots
"""
def isConnected(self):
"""Check if any slots are connected to this signal."""
def connectionCount(self):
"""Get the number of connected slots."""
def blockSignals(self, blocked):
"""Block or unblock signal emission."""
def signalsBlocked(self):
"""Check if signals are blocked."""pyTTkSlot decorator marks functions as slots for signal connection.
def pyTTkSlot(*types):
"""
Decorator to mark a function as a slot.
Parameters:
- types: Expected parameter types (optional, for type checking)
Returns:
Decorated function that can be connected to signals
Usage:
@pyTTkSlot()
def my_slot():
pass
@pyTTkSlot(int, str)
def typed_slot(number, text):
pass
"""Event objects that carry information about user interactions and system events.
class TTkKeyEvent:
def __init__(self, type, key, text="", modifiers=0):
"""
Initialize a keyboard event.
Parameters:
- type (int): Event type (KeyPress, KeyRelease)
- key (int): Key code constant
- text (str): Text representation of key
- modifiers (int): Modifier keys (Ctrl, Alt, Shift)
"""
def type(self):
"""Get the event type."""
def key(self):
"""Get the key code."""
def text(self):
"""Get the text representation."""
def modifiers(self):
"""Get the modifier keys."""
def matches(self, key_sequence):
"""Check if event matches a key sequence."""
def accept(self):
"""Accept the event (stops propagation)."""
def ignore(self):
"""Ignore the event (allows propagation)."""
def isAccepted(self):
"""Check if event is accepted."""
class TTkMouseEvent:
def __init__(self, type, pos, button, buttons, modifiers):
"""
Initialize a mouse event.
Parameters:
- type (int): Event type (MousePress, MouseRelease, MouseMove)
- pos (TTkPoint): Mouse position
- button (int): Button that caused the event
- buttons (int): All pressed buttons
- modifiers (int): Modifier keys
"""
def type(self):
"""Get the event type."""
def pos(self):
"""Get the mouse position."""
def x(self):
"""Get the x coordinate."""
def y(self):
"""Get the y coordinate."""
def button(self):
"""Get the button that caused the event."""
def buttons(self):
"""Get all pressed buttons."""
def modifiers(self):
"""Get the modifier keys."""
def accept(self):
"""Accept the event."""
def ignore(self):
"""Ignore the event."""
def isAccepted(self):
"""Check if event is accepted."""TTkTimer provides timing functionality for periodic events and delayed actions.
class TTkTimer:
def __init__(self, parent=None):
"""Initialize a timer."""
def start(self, msec=None):
"""
Start the timer.
Parameters:
- msec (int): Interval in milliseconds (optional if set before)
"""
def stop(self):
"""Stop the timer."""
def setInterval(self, msec):
"""Set the timer interval in milliseconds."""
def interval(self):
"""Get the timer interval."""
def setSingleShot(self, singleShot):
"""Set whether timer fires only once."""
def isSingleShot(self):
"""Check if timer is single-shot."""
def isActive(self):
"""Check if timer is active."""
def remainingTime(self):
"""Get remaining time until next timeout."""
# Signals
timeout: pyTTkSignal # Emitted when timer times outTTkShortcut provides keyboard shortcut handling for application actions.
class TTkShortcut:
def __init__(self, keySequence, parent=None):
"""
Initialize a keyboard shortcut.
Parameters:
- keySequence (str): Key sequence (e.g., "Ctrl+S", "Alt+F4")
- parent: Parent widget for shortcut scope
"""
def setKey(self, keySequence):
"""Set the key sequence."""
def key(self):
"""Get the key sequence."""
def setEnabled(self, enabled):
"""Enable/disable the shortcut."""
def isEnabled(self):
"""Check if shortcut is enabled."""
def setContext(self, context):
"""Set the shortcut context scope."""
def context(self):
"""Get the shortcut context scope."""
def setAutoRepeat(self, autoRepeat):
"""Enable/disable auto-repeat."""
def autoRepeat(self):
"""Check if auto-repeat is enabled."""
# Signals
activated: pyTTkSignal # Emitted when shortcut is activated
activatedAmbiguously: pyTTkSignal # Emitted for ambiguous activationimport TermTk as ttk
class MyWidget(ttk.TTkWidget):
# Define custom signal
dataChanged = ttk.pyTTkSignal(str)
def __init__(self, parent=None):
super().__init__(parent=parent)
self._data = ""
def setData(self, data):
if self._data != data:
self._data = data
self.dataChanged.emit(data) # Emit signal
def data(self):
return self._data
# Usage
root = ttk.TTk()
widget = MyWidget(parent=root)
# Define slot function
@ttk.pyTTkSlot(str)
def on_data_changed(new_data):
print(f"Data changed to: {new_data}")
# Connect signal to slot
widget.dataChanged.connect(on_data_changed)
# Trigger signal
widget.setData("Hello World") # Prints: "Data changed to: Hello World"
root.mainloop()import TermTk as ttk
root = ttk.TTk()
container = ttk.TTkContainer(parent=root)
layout = ttk.TTkVBoxLayout()
button1 = ttk.TTkButton(text="Button 1")
button2 = ttk.TTkButton(text="Button 2")
label = ttk.TTkLabel(text="No button clicked yet")
# Define slot methods
@ttk.pyTTkSlot()
def button1_clicked():
label.setText("Button 1 was clicked!")
@ttk.pyTTkSlot()
def button2_clicked():
label.setText("Button 2 was clicked!")
# Connect signals to slots
button1.clicked.connect(button1_clicked)
button2.clicked.connect(button2_clicked)
layout.addWidget(button1)
layout.addWidget(button2)
layout.addWidget(label)
container.setLayout(layout)
root.mainloop()import TermTk as ttk
root = ttk.TTk()
container = ttk.TTkContainer(parent=root)
label = ttk.TTkLabel(text="Timer: 0", parent=container)
counter = 0
# Create timer
timer = ttk.TTkTimer()
timer.setInterval(1000) # 1 second
# Define timer slot
@ttk.pyTTkSlot()
def update_counter():
global counter
counter += 1
label.setText(f"Timer: {counter}")
# Connect timer to slot
timer.timeout.connect(update_counter)
# Start timer
timer.start()
root.mainloop()import TermTk as ttk
class KeyCaptureWidget(ttk.TTkWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setFocusPolicy(ttk.TTkConstant.StrongFocus)
self._label = ttk.TTkLabel(parent=self, text="Press any key...")
def keyEvent(self, evt):
if evt.type() == ttk.TTkConstant.KeyPress:
key_name = self.get_key_name(evt.key())
text = f"Key pressed: {key_name}"
if evt.modifiers() & ttk.TTkConstant.ControlModifier:
text += " (with Ctrl)"
if evt.modifiers() & ttk.TTkConstant.AltModifier:
text += " (with Alt)"
if evt.modifiers() & ttk.TTkConstant.ShiftModifier:
text += " (with Shift)"
self._label.setText(text)
evt.accept()
else:
super().keyEvent(evt)
def get_key_name(self, key):
# Convert key code to readable name
key_names = {
ttk.TTkConstant.Key_Return: "Return",
ttk.TTkConstant.Key_Escape: "Escape",
ttk.TTkConstant.Key_Space: "Space",
ttk.TTkConstant.Key_Up: "Up Arrow",
ttk.TTkConstant.Key_Down: "Down Arrow",
ttk.TTkConstant.Key_Left: "Left Arrow",
ttk.TTkConstant.Key_Right: "Right Arrow",
}
return key_names.get(key, f"Key_{key}")
root = ttk.TTk()
widget = KeyCaptureWidget(parent=root)
widget.setFocus()
root.mainloop()import TermTk as ttk
class ClickTracker(ttk.TTkWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
self._click_count = 0
self._label = ttk.TTkLabel(parent=self, text="Click count: 0")
def mousePressEvent(self, evt):
if evt.button() == ttk.TTkConstant.LeftButton:
self._click_count += 1
self._label.setText(f"Click count: {self._click_count}")
print(f"Left click at ({evt.x()}, {evt.y()})")
elif evt.button() == ttk.TTkConstant.RightButton:
print(f"Right click at ({evt.x()}, {evt.y()})")
evt.accept()
root = ttk.TTk()
tracker = ClickTracker(parent=root)
root.mainloop()import TermTk as ttk
root = ttk.TTk()
container = ttk.TTkContainer(parent=root)
layout = ttk.TTkVBoxLayout()
label = ttk.TTkLabel(text="Use Ctrl+S to save, Ctrl+Q to quit")
text_edit = ttk.TTkTextEdit()
layout.addWidget(label)
layout.addWidget(text_edit)
container.setLayout(layout)
# Create shortcuts
save_shortcut = ttk.TTkShortcut("Ctrl+S", container)
quit_shortcut = ttk.TTkShortcut("Ctrl+Q", container)
# Define shortcut handlers
@ttk.pyTTkSlot()
def save_action():
print("Save action triggered!")
label.setText("File saved!")
@ttk.pyTTkSlot()
def quit_action():
print("Quit action triggered!")
root.quit()
# Connect shortcuts
save_shortcut.activated.connect(save_action)
quit_shortcut.activated.connect(quit_action)
root.mainloop()import TermTk as ttk
root = ttk.TTk()
container = ttk.TTkContainer(parent=root)
layout = ttk.TTkVBoxLayout()
button = ttk.TTkButton(text="Click me")
toggle_button = ttk.TTkButton(text="Toggle Connection")
label = ttk.TTkLabel(text="Connection active")
@ttk.pyTTkSlot()
def button_clicked():
label.setText("Button was clicked!")
@ttk.pyTTkSlot()
def toggle_connection():
if button.clicked.isConnected():
button.clicked.disconnect(button_clicked)
toggle_button.setText("Connect")
label.setText("Connection disabled")
else:
button.clicked.connect(button_clicked)
toggle_button.setText("Disconnect")
label.setText("Connection active")
# Initial connection
button.clicked.connect(button_clicked)
toggle_button.clicked.connect(toggle_connection)
layout.addWidget(button)
layout.addWidget(toggle_button)
layout.addWidget(label)
container.setLayout(layout)
root.mainloop()Install with Tessl CLI
npx tessl i tessl/pypi-pytermtk