pyTermTk

Pythonのターミナルツールキットライブラリ。Qt風のAPIを提供し、レイアウトマネージャー、シグナル・スロット機能を備えた本格的なTUIフレームワークです。

TUIQt-likeSignalsSlotsLayoutFramework

GitHub概要

ceccopierangiolieugenio/pyTermTk

Python Terminal Toolkit - a Spiced Up Cross Compatible TUI Library 🌶️

スター744
ウォッチ7
フォーク31
作成日:2021年2月16日
言語:Python
ライセンス:MIT License

トピックス

asciiascii-graphicslibrarypyodidepytermtkpythonterminalterminal-emulatorterminal-graphicsterminal-multiplexertext-editortuitui-apptui-editortui-librarytutorialuiui-designui-libraryuser-interface

スター履歴

ceccopierangiolieugenio/pyTermTk Star History
データ取得日時: 2025/7/25 06:23

pyTermTk

pyTermTkは、Pythonのターミナルツールキットライブラリです。Qt風のAPIを採用し、シグナル・スロット機能、レイアウトマネージャー、イベント駆動型プログラミングを提供する本格的なTUIフレームワークです。デスクトップアプリケーション開発者にとって親しみやすい設計となっています。

主な特徴

Qt風API

  • 親しみやすい設計: QtライクなAPIで学習コストを削減
  • オブジェクト指向: クラスベースの設計思想
  • 一貫性: Qtと類似したメソッド名と構造

シグナル・スロット

  • イベント駆動: シグナルとスロットによる疎結合
  • カスタムシグナル: 独自のシグナル定義が可能
  • 非同期処理: 効率的なイベント処理

レイアウト管理

  • 自動配置: 動的なウィジェット配置
  • サイズ調整: 自動的なサイズ計算
  • ネスト構造: 複雑なレイアウトの構築

インストール

pip install pyTermTk

基本的な使用方法

シンプルなアプリケーション

#!/usr/bin/env python3

import TermTk as ttk

root = ttk.TTk()

# メインウィンドウの作成
win = ttk.TTkWindow(parent=root, pos=(1,1), size=(50,20), title="Hello pyTermTk")

# ラベルウィジェットの追加
label = ttk.TTkLabel(parent=win, pos=(2,2), text="Hello, World!")

# ボタンの追加
button = ttk.TTkButton(parent=win, pos=(2,4), text="Click Me!")

def button_clicked():
    label.setText("Button Clicked!")

# シグナル・スロット接続
button.clicked.connect(button_clicked)

root.mainloop()

レイアウトマネージャーの使用

#!/usr/bin/env python3

import TermTk as ttk

root = ttk.TTk()

# メインウィンドウ
win = ttk.TTkWindow(parent=root, pos=(1,1), size=(60,25), title="Layout Example")

# 垂直レイアウト
vbox = ttk.TTkVBoxLayout()
win.setLayout(vbox)

# ヘッダー
header = ttk.TTkLabel(text="pyTermTk Layout Example")
vbox.addWidget(header)

# 水平レイアウト
hbox = ttk.TTkHBoxLayout()

# 左側パネル
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 = 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 = ttk.TTkLabel(text="Status: Ready")
vbox.addWidget(footer)

root.mainloop()

高度な機能

カスタムウィジェット

#!/usr/bin/env python3

import TermTk as ttk

class CounterWidget(ttk.TTkWidget):
    # カスタムシグナル定義
    valueChanged = ttk.pyTTkSignal(int)
    
    def __init__(self, initial_value=0, **kwargs):
        super().__init__(**kwargs)
        self._value = initial_value
        
        # レイアウト設定
        layout = ttk.TTkHBoxLayout()
        self.setLayout(layout)
        
        # コンポーネント
        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)
        
        # シグナル接続
        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)

# カスタムウィジェットの使用
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()

タブとメニュー

#!/usr/bin/env python3

import TermTk as ttk

root = ttk.TTk()

# メインウィンドウ
win = ttk.TTkWindow(parent=root, pos=(1,1), size=(70,30), title="Tabs and Menus")

# メニューバー
menubar = ttk.TTkMenuBar(parent=win)

# ファイルメニュー
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 = menubar.addMenu("Edit")
edit_menu.addAction("Copy").triggered.connect(lambda: print("Copy"))
edit_menu.addAction("Paste").triggered.connect(lambda: print("Paste"))

# タブウィジェット
tab_widget = ttk.TTkTabWidget(parent=win, pos=(0,1), size=(70,28))

# タブ1: テキストエディタ
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")

# タブ2: 設定
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")

# タブ3: 情報
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()

ダイアログとポップアップ

#!/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)
        
        # ボタン群
        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)
        
        # 結果表示
        self.result_label = ttk.TTkLabel(text="Result will appear here")
        layout.addWidget(self.result_label)
        
        # シグナル接続
        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()

他のライブラリとの比較

特徴pyTermTkTextualUrwidPyTermGUI
API設計Qt風独自独自YAML風
レイアウト自動CSS風手動設定
シグナル・スロット×××
学習コストQt経験者は低
機能の豊富さ

使用事例

  • Qt移植: Qtアプリケーションのターミナル版
  • 複雑なTUIアプリ: 多機能なターミナルアプリケーション
  • 開発ツール: IDE風のターミナルツール
  • 管理画面: システム管理用のTUIツール

コミュニティとサポート

  • 開発: アクティブな開発が継続中
  • ドキュメント: 充実したAPIリファレンス
  • 例題: Qt経験者向けのサンプル
  • Qt互換性: Qt APIとの高い親和性

pyTermTkは、Qt開発者にとって親しみやすいAPIを提供し、本格的なTUIアプリケーション開発を可能にする現代的なフレームワークです。