Go言語(golang)でTUIアプリを作ろう ( その3 tviewの基本構造 )

tviewのWidgetとEventを理解しよう。


tviewの基本機能を理解するには、まず、下記のドキュメンテーションを見ることが第一歩でしょう。


(1) Widget一覧

画面を下に少しスクロールしたところに、”Widgets”という項目があります。基本的な部品は揃っているように見えますが、細部を見ていくと気になる点も少なくありません。それは後で述べるとして、とりあえずWidget一覧を見ていきましょう。

Widget 概要 利用
TextView 表示フィールド。マルチライン可。
Table テーブル形式のデータ。スクロール化。
TreeView ツリー形式の表示
List 一覧表示
InputField 入力フィールド。マルチラインをサポートしていないようだ。
DropDown ドロップダウン形式の表示
Checkbox チェックボックス
Button ボタン
Form 入力フォーム。Widgetというより雛形で再利用性に乏しい。
Modal 単なるメッセージボックス。再利用性に乏しい。
Grid 二次元のコンテナ。
Flex 一次元のコンテナ。縦、横の方向を選択する。
Pages 画面に複数ページを切り替えて表示できるコンテナ。

なお、これからの開発に使用する予定のWidgetには、「○」を付けておきました。


(2) オブジェクト構造

オブジェクトの構造について重要なポイントが、上記ドキュメント中盤に”Type Hierarchy”として記述されています。

All widgets listed above contain the Box type. All of Box’s functions are therefore available for all widgets, too.

All widgets also implement the Primitive interface.

というところです。
要するに、すべてのWidgetは、Primitiveインターフェースを実装、Boxオブジェクトを継承しているということです。下記に概念図を示しておきます。


(3) WidgetとEvent

次に、WidgetEventの関係ですが、最上部のWidgetを、ApplicationオブジェクトのSetRootメソッドにセットすることでアプリケーションが開始されます。
入力Eventは、各WidgetのSetInputCaptureメソッドや、SetDoneFuncメソッドで処理されることになります。これも概念図を示しておきます。

プログラミング例も示しておきましょう。
下記のプログラムでは、WidgetinputField一つだけですので、このインスタンスをApplicationSetRootメソッドにセットしています。また、入力完了イベントは、SetDoneFuncメソッドで処理しています。

func main() {  
	app := tview.NewApplication()  
	inputField := tview.NewInputField().  
		SetLabel("文字を入力: ").  
		SetFieldWidth(10).  
		SetDoneFunc(func(key tcell.Key) {  
			app.Stop()  
		})  
	if err := app.SetRoot(inputField, true).EnableMouse(true).Run(); err != nil {  
		panic(err)  
	}  

Python Urwidでは、各Widgetで処理されないイベントを一括でハンドリングできるunhandled inputが用意されていましたが、tviewでは、appにもSetInputCaptureメソッドがありますので、ここで処理すれば良さそうです。


(4) 問題点

先にも少し触れましたが、tviewのWidgetには気になる点が複数あります。

  • データ入力を司るinputFieldが、複数行入力をサポートしていないこと。
    これは、最も大きな問題です。
  • ダイアログ関係がないこと。
    Modalが一見その様に見えますが、実はメッセージボックスそのもので応用が効きません。これでは、Widgetとは言えないでしょう
  • Formも同様。
    入力画面をサポートするものですが、作成できる画面フォーマットは決まっており、汎用性がありません。

こんなところでしょうか。前途多難が懸念されますが、その予想は....外れませんでしたね(笑)。