pyTermTk
A Python terminal toolkit library. Provides a Qt-like API with layout managers and signal-slot functionality as a full-fledged TUI framework.
GitHub Overview
ceccopierangiolieugenio/pyTermTk
Python Terminal Toolkit - a Spiced Up Cross Compatible TUI Library 🌶️
Stars744
Watchers7
Forks31
Created:February 16, 2021
Language:Python
License:MIT License
Topics
asciiascii-graphicslibrarypyodidepytermtkpythonterminalterminal-emulatorterminal-graphicsterminal-multiplexertext-editortuitui-apptui-editortui-librarytutorialuiui-designui-libraryuser-interface
Star History
Data as of: 7/25/2025, 06:23 AM
pyTermTk
pyTermTk is a Python terminal toolkit library. It adopts a Qt-like API and provides signal-slot functionality, layout managers, and event-driven programming as a full-fledged TUI framework. Its design is familiar to desktop application developers.
Key Features
Qt-like API
- Familiar Design: Qt-like API reduces learning costs
- Object-Oriented: Class-based design philosophy
- Consistency: Similar method names and structure to Qt
Signal-Slot System
- Event-Driven: Loose coupling through signals and slots
- Custom Signals: Can define custom signals
- Asynchronous Processing: Efficient event handling
Layout Management
- Automatic Placement: Dynamic widget placement
- Size Adjustment: Automatic size calculation
- Nested Structure: Construction of complex layouts
Installation
pip install pyTermTk
Basic Usage
Simple Application
#!/usr/bin/env python3
import TermTk as ttk
root = ttk.TTk()
# Create main window
win = ttk.TTkWindow(parent=root, pos=(1,1), size=(50,20), title="Hello pyTermTk")
# Add label widget
label = ttk.TTkLabel(parent=win, pos=(2,2), text="Hello, World!")
# Add button
button = ttk.TTkButton(parent=win, pos=(2,4), text="Click Me!")
def button_clicked():
label.setText("Button Clicked!")
# Connect signal-slot
button.clicked.connect(button_clicked)
root.mainloop()
Using Layout Managers
#!/usr/bin/env python3
import TermTk as ttk
root = ttk.TTk()
# Main window
win = ttk.TTkWindow(parent=root, pos=(1,1), size=(60,25), title="Layout Example")
# Vertical layout
vbox = ttk.TTkVBoxLayout()
win.setLayout(vbox)
# Header
header = ttk.TTkLabel(text="pyTermTk Layout Example")
vbox.addWidget(header)
# Horizontal layout
hbox = ttk.TTkHBoxLayout()
# Left panel
left_panel = ttk.TTkFrame()
left_layout = ttk.TTkVBoxLayout()
left_panel.setLayout(left_layout)
left_layout.addWidget(ttk.TTkLabel(text="Left Panel"))
left_layout.addWidget(ttk.TTkButton(text="Button 1"))
left_layout.addWidget(ttk.TTkButton(text="Button 2"))
# Right panel
right_panel = ttk.TTkFrame()
right_layout = ttk.TTkVBoxLayout()
right_panel.setLayout(right_layout)
right_layout.addWidget(ttk.TTkLabel(text="Right Panel"))
right_layout.addWidget(ttk.TTkLineEdit())
right_layout.addWidget(ttk.TTkTextEdit())
hbox.addWidget(left_panel)
hbox.addWidget(right_panel)
vbox.addLayout(hbox)
# Footer
footer = ttk.TTkLabel(text="Status: Ready")
vbox.addWidget(footer)
root.mainloop()
Advanced Features
Custom Widgets
#!/usr/bin/env python3
import TermTk as ttk
class CounterWidget(ttk.TTkWidget):
# Custom signal definition
valueChanged = ttk.pyTTkSignal(int)
def __init__(self, initial_value=0, **kwargs):
super().__init__(**kwargs)
self._value = initial_value
# Layout setup
layout = ttk.TTkHBoxLayout()
self.setLayout(layout)
# Components
self._label = ttk.TTkLabel(text=f"Count: {self._value}")
self._dec_btn = ttk.TTkButton(text="-")
self._inc_btn = ttk.TTkButton(text="+")
layout.addWidget(self._dec_btn)
layout.addWidget(self._label)
layout.addWidget(self._inc_btn)
# Signal connections
self._inc_btn.clicked.connect(self._increment)
self._dec_btn.clicked.connect(self._decrement)
def _increment(self):
self._value += 1
self._update_display()
self.valueChanged.emit(self._value)
def _decrement(self):
self._value -= 1
self._update_display()
self.valueChanged.emit(self._value)
def _update_display(self):
self._label.setText(f"Count: {self._value}")
def value(self):
return self._value
def setValue(self, value):
self._value = value
self._update_display()
self.valueChanged.emit(self._value)
# Using custom widget
root = ttk.TTk()
win = ttk.TTkWindow(parent=root, pos=(1,1), size=(50,15), title="Custom Widget")
layout = ttk.TTkVBoxLayout()
win.setLayout(layout)
counter = CounterWidget(initial_value=10)
status_label = ttk.TTkLabel(text="Value: 10")
def on_value_changed(value):
status_label.setText(f"Value: {value}")
counter.valueChanged.connect(on_value_changed)
layout.addWidget(counter)
layout.addWidget(status_label)
root.mainloop()
Tabs and Menus
#!/usr/bin/env python3
import TermTk as ttk
root = ttk.TTk()
# Main window
win = ttk.TTkWindow(parent=root, pos=(1,1), size=(70,30), title="Tabs and Menus")
# Menu bar
menubar = ttk.TTkMenuBar(parent=win)
# File menu
file_menu = menubar.addMenu("File")
file_menu.addAction("New").triggered.connect(lambda: print("New file"))
file_menu.addAction("Open").triggered.connect(lambda: print("Open file"))
file_menu.addSeparator()
file_menu.addAction("Exit").triggered.connect(root.quit)
# Edit menu
edit_menu = menubar.addMenu("Edit")
edit_menu.addAction("Copy").triggered.connect(lambda: print("Copy"))
edit_menu.addAction("Paste").triggered.connect(lambda: print("Paste"))
# Tab widget
tab_widget = ttk.TTkTabWidget(parent=win, pos=(0,1), size=(70,28))
# Tab 1: Text editor
tab1 = ttk.TTkWidget()
tab1_layout = ttk.TTkVBoxLayout()
tab1.setLayout(tab1_layout)
text_edit = ttk.TTkTextEdit()
tab1_layout.addWidget(ttk.TTkLabel(text="Text Editor Tab"))
tab1_layout.addWidget(text_edit)
tab_widget.addTab(tab1, "Editor")
# Tab 2: Settings
tab2 = ttk.TTkWidget()
tab2_layout = ttk.TTkVBoxLayout()
tab2.setLayout(tab2_layout)
tab2_layout.addWidget(ttk.TTkLabel(text="Settings Tab"))
tab2_layout.addWidget(ttk.TTkCheckbox(text="Enable feature A"))
tab2_layout.addWidget(ttk.TTkCheckbox(text="Enable feature B"))
combo = ttk.TTkComboBox()
combo.addItems(["Option 1", "Option 2", "Option 3"])
tab2_layout.addWidget(combo)
tab_widget.addTab(tab2, "Settings")
# Tab 3: Information
tab3 = ttk.TTkWidget()
tab3_layout = ttk.TTkVBoxLayout()
tab3.setLayout(tab3_layout)
tab3_layout.addWidget(ttk.TTkLabel(text="Information Tab"))
tab3_layout.addWidget(ttk.TTkLabel(text="pyTermTk Version: 0.x.x"))
tab3_layout.addWidget(ttk.TTkLabel(text="Platform: Terminal"))
tab_widget.addTab(tab3, "Info")
root.mainloop()
Dialogs and Popups
#!/usr/bin/env python3
import TermTk as ttk
class MainWindow(ttk.TTkWindow):
def __init__(self, **kwargs):
super().__init__(**kwargs)
layout = ttk.TTkVBoxLayout()
self.setLayout(layout)
# Button group
msg_btn = ttk.TTkButton(text="Show Message")
input_btn = ttk.TTkButton(text="Show Input Dialog")
confirm_btn = ttk.TTkButton(text="Show Confirmation")
layout.addWidget(ttk.TTkLabel(text="Dialog Examples"))
layout.addWidget(msg_btn)
layout.addWidget(input_btn)
layout.addWidget(confirm_btn)
# Result display
self.result_label = ttk.TTkLabel(text="Result will appear here")
layout.addWidget(self.result_label)
# Signal connections
msg_btn.clicked.connect(self.show_message)
input_btn.clicked.connect(self.show_input_dialog)
confirm_btn.clicked.connect(self.show_confirmation)
def show_message(self):
dialog = ttk.TTkMessageBox(
parent=self,
title="Information",
text="This is a message dialog!"
)
dialog.exec()
self.result_label.setText("Message dialog shown")
def show_input_dialog(self):
dialog = ttk.TTkInputDialog(
parent=self,
title="Input",
label="Enter your name:"
)
if dialog.exec() == ttk.TTkK.Accepted:
text = dialog.textValue()
self.result_label.setText(f"Input: {text}")
else:
self.result_label.setText("Input canceled")
def show_confirmation(self):
dialog = ttk.TTkMessageBox(
parent=self,
title="Confirmation",
text="Are you sure?",
standardButtons=ttk.TTkMessageBox.Yes | ttk.TTkMessageBox.No
)
result = dialog.exec()
if result == ttk.TTkMessageBox.Yes:
self.result_label.setText("Confirmed: Yes")
else:
self.result_label.setText("Confirmed: No")
root = ttk.TTk()
win = MainWindow(parent=root, pos=(1,1), size=(60,20), title="Dialog Example")
root.mainloop()
Comparison with Other Libraries
Feature | pyTermTk | Textual | Urwid | PyTermGUI |
---|---|---|---|---|
API Design | Qt-like | Custom | Custom | YAML-like |
Layout | Automatic | CSS-like | Manual | Configuration |
Signal-Slot | ○ | × | × | × |
Learning Curve | Low for Qt users | Medium | High | Medium |
Feature Richness | High | High | High | Medium |
Use Cases
- Qt Porting: Terminal versions of Qt applications
- Complex TUI Apps: Feature-rich terminal applications
- Development Tools: IDE-like terminal tools
- Management Interfaces: TUI tools for system administration
Community and Support
- Development: Active ongoing development
- Documentation: Comprehensive API reference
- Examples: Samples for Qt-experienced developers
- Qt Compatibility: High affinity with Qt API
pyTermTk is a modern framework that provides a familiar API for Qt developers and enables serious TUI application development.