【PythonでつくるTUI(Text User Interface)】cursesで作るTUIアプリの作り方

curses
けんろう
けんろう

Pythonでアプリを作りたい人の多くは、リッチなグラフィックを持つアプリを想定していると思いますが、本当にリッチなグラフィックは必要ですか?

ちょっとしたアプリなら、TUI(テキストユーザインターフェース)アプリで済む場合が多いと思います。
今回は、cursesを使った、TUIアプリの作り方を紹介します。 

この記事に載っているサンプルコードをコピーして、Pythonで実行すれば、簡単に動きを確認できますので、是非試してみて下さい。

この記事では、初心者にもわかりやすいように、各処理の内容を、サンプルコード内にコメントとして載せています。

スポンサーリンク

今回作成するアプリ

今回紹介するアプリは、

・ウィンドウサイズを表示
・任意のテキストを表示
・押下されたキー番号を表示
・カーソル位置を表示
・q押下で終了

環境準備

本アプリを動かすために、以下のライブラリが必要です。

curses:テキストユーザインターフェースのためのライブラリ

公式サイトは、以下です。

インストール方法は、以下です。

pip install windows-curses

サンプルコード

#!usr/bin/env python
# -*- coding: utf-8 -*-

import sys,os
import curses

def func_draw(stdscr):

    # 初期化
    k = 0
    cursor_x = 0
    cursor_y = 0

    # 画面の初期化
    stdscr.clear()
    stdscr.refresh()

    # カラーの定義
    curses.start_color()
    curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK)    # カラー1は、文字色をシアン、背景色を黒
    curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)    # カラー2は、文字色を赤、背景色を黒
    curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_YELLOW)    # カラー3は、文字色を黒、背景色を黄

    # ”q”が押下されるまで、ループ
    while (k != ord('q')):

        # 画面の初期化
        stdscr.clear()

        # 画面の最大値を取得(高さ、幅)
        height, width = stdscr.getmaxyx()

        # ーーカーソル位置の表示ーー
        # 押下されたキーが方向ボタンなら、カーソル位置を更新
        if k == curses.KEY_DOWN:
            cursor_y = cursor_y + 1
        elif k == curses.KEY_UP:
            cursor_y = cursor_y - 1
        elif k == curses.KEY_RIGHT:
            cursor_x = cursor_x + 1
        elif k == curses.KEY_LEFT:
            cursor_x = cursor_x - 1

        # カーソル位置が枠から外れている場合の補正
        cursor_x = max(0, cursor_x)
        cursor_x = min(width-1, cursor_x)

        cursor_y = max(0, cursor_y)
        cursor_y = min(height-1, cursor_y)

        # カーソル位置の表示
        whstr = "Width: {}, Height: {}".format(width, height)
        stdscr.addstr(0, 0, whstr, curses.color_pair(1))    # 文字列whstrを(0,0)にカラー1で表示する

        # ーー文字列の表示ーー
        # 文字列の作成(私の環境windows10では、文字が重なってしまうため、文字の間にスペースを入れて見栄え改善)
        title = "Curses サ ン プ ル "[:width-1]
        subtitle = "こ ん に ち は ラ ズ パ イ の 実 を よ ろ し く お 願 い し ま す "[:width-1]
        keystr = "最 後 に 押 下 さ れ た キ ー は : {}".format(k)[:width-1]
        statusbarstr = " 'q' を 押 下 す る と 終 了  | ラ ズ パ イ の 実  | カ ー ソ ル 位 置 : {}, {}".format(cursor_x, cursor_y)

        if k == 0:
            keystr = "キ ー は 押 さ れ て い ま せ ん ..."[:width-1]

        # 文字列の表示位置の算出(画面の中央に来るように計算している)
        start_x_title = int((width // 2) - (len(title) // 2) - len(title) % 2)
        start_x_subtitle = int((width // 2) - (len(subtitle) // 2) - len(subtitle) % 2)
        start_x_keystr = int((width // 2) - (len(keystr) // 2) - len(keystr) % 2)
        start_y = int((height // 2) - 2)

        # 文字列statusbarstrの表示設定
        stdscr.attron(curses.color_pair(3))     # カラー3をONに切り替え
        stdscr.addstr(height-1, 0, statusbarstr)    # 文字列statusbarstrを、一番下に配置
        stdscr.addstr(height-1, len(statusbarstr), " " * (width - len(statusbarstr) - 1))
        stdscr.attroff(curses.color_pair(3))     # カラー3をOFFに切り替え

        # 文字列titleの表示設定
        stdscr.attron(curses.color_pair(2))     # カラー2をONに切り替え
        stdscr.attron(curses.A_BOLD)     # 太字をONに切り替え
        stdscr.addstr(start_y, start_x_title, title)    # 文字列titleを配置
        stdscr.attroff(curses.color_pair(2))     # カラー2をOFFに切り替え
        stdscr.attroff(curses.A_BOLD)     # 太字をOFFに切り替え

        # 残りの文字列の表示設定
        stdscr.addstr(start_y + 1, start_x_subtitle, subtitle)      # 文字列subtitleを配置
        stdscr.addstr(start_y + 3, (width // 2) - 2, '-' * 4)      # '-'を4つ並べて、配置
        stdscr.addstr(start_y + 5, start_x_keystr, keystr)      # 文字列keystrを配置

        stdscr.move(cursor_y, cursor_x)     # カーソルを移動

        # 画面をリフレッシュする
        stdscr.refresh()

        # 次のキー入力を待つ
        k = stdscr.getch()

    # qを押されたら、ターミナルの設定を元に戻す
    curses.nocbreak()
    stdscr.keypad(False)
    curses.echo()
    curses.endwin()

# メイン関数
def main():
    curses.wrapper(func_draw)

if __name__ == "__main__":
    main()

このまま実行してもいいですが、よりアプリケーションっぽくするために、実行形式に変換します。

pyinstaller sample.py --onefile

以下のコマンドを実行すると、exeファイルが生成されます。

そのexeファイルをダブルクリックすると、以下の画面を持つアプリが起動します。

上から、
・ウィンドウサイズ
・テキスト「Curses サ ン プ ル」
・テキスト「こ ん に ち は ラ ズ パ イ の 実 を よ ろ し く お 願 い し ま す」
・テキスト「ーーーー」
・押下されたキー番号
・カーソル位置

なにかのキーを押下すると、そのキーに応じたキー番号が表示されます。
また、矢印キーを動かせば、カーソルが動き、カーソル位置も更新されます。

\ Pythonで遊ぶなら、ラズパイがお薦め。特にこのキーボード付きがオススメです /

まとめ

今回は、cursesを使用したTUI(テキストユーザインターフェース)アプリの作り方を紹介しました。

コメント

タイトルとURLをコピーしました