
ターミナル環境で動くCLIツールはシンプルで便利ですが、ユーザーにとって扱いやすいリッチな操作画面(TUI: Terminal User Interface)を作りたいと感じたことはありませんか?Textualを使えば、Webフロントエンドのように洗練されたレイアウトやイベント駆動型のUIを、Pythonだけで驚くほど簡単に実装できます。
Textualの概要
Textualは、ターミナル上で美麗かつ高度なUIを構築するためのPythonフレームワークです。著名なターミナル装飾ライブラリ「Rich」の開発元が手掛けており、CSSに似たスタイルシート(TCSS)を用いて画面をデザインできる点が大きな特徴です。非同期処理(asyncio)をベースにしており、スムーズな画面更新や複雑なユーザー入力へのリアルタイムな反応が可能です。
Web制作のCSSと同じような感覚でレイアウトを組めるので、フロントエンド経験がある方ならすぐに馴染めると思います。
Textualを利用するメリット
- CSSに似た直感的なスタイリング(TCSS)
デザインをロジックから分離し、色やレイアウト、マージンなどをCSSライクな構文で指定できます。FlexboxやGridに近いレイアウト構築がターミナル上で実現します。 - 豊富な組み込みウィジェット
ボタン、入力欄、テーブル、ツリー表示、進捗バーなど、実用的なGUIコンポーネントがあらかじめ用意されています。 - キーボード・マウス両対応
キーボードショートカットだけでなく、マウスによるクリックやスクロール操作も標準でサポートされています。
サンプルコード
シンプルなストップウォッチ風のカウンターUIを作成してみましょう。ボタンを押すとカウントが増加します。
from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, Button, Static
class CounterApp(App):
"""シンプルなカウンターアプリケーション"""
CSS = """
Screen {
align: center middle;
}
#counter-view {
width: 30;
height: 5;
border: solid green;
content-align: center middle;
text-style: bold;
margin-bottom: 1;
}
Button {
width: 16;
}
"""
def __init__(self):
super().__init__()
self.count = 0
def compose(self) -> ComposeResult:
yield Header()
yield Static("Count: 0", id="counter-view")
yield Button("Count Up", variant="primary", id="btn-count")
yield Footer()
def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id == "btn-count":
self.count += 1
static_view = self.query_one("#counter-view", Static)
static_view.update(f"Count: {self.count}")
if __name__ == "__main__":
app = CounterApp()
app.run()このコードを実行すると、ターミナル全体にヘッダー、中央揃えのカウンター、ボタン、そしてフッターが配置されたモダンな画面が立ち上がります。
CSSプロパティを外部ファイル(.tcss)に切り出すこともできるので、コードベースが大きくなっても保守しやすいのが魅力的ですね。

みーちゃんのワンポイント
Textualを開発するときは、ぜひtextual run --dev your_app.pyコマンドを活用してください。別ターミナルでtextual consoleを起動しておくと、ログのリアルタイム確認やTCSSのホットリロード(自動再読み込み)が有効になり、開発効率が劇的に向上します。

