kivyのスクロール可能なラベルのカスタムウィジェット

PythonプログラムでGUIを作成するkivyでスクロール可能なラベルのカスタムウィジェットを作ったメモ

概要

Pythonのマルチプラットフォーム向けGUIライブラリkivyでお試しプログラムを作っていた時、 ログ出力をスクロール可能にしたい(TeraTermみたいなターミナル表示のイメージ)と思い作ってみたけれど、 汎用的に使えそうな気がしたのでカスタムウィジェットとしてまとめてみた。

解説

解説するほど理解してないけど…
kivyでは文字列を表示するのにLabelウィジェットを使うらしい(AndroidStudioでいうことろのTextView?)。
で、表示をスクロールするにはScrollViewウィジェットを使う(AndroidStudioでもScrollView)。
文字列をスクロールするには、ScrollViewの中にLabelを配置してやれば良いのだけれど、「配置しておしまい」という訳でもなく、 色々と細々と下処理が必要になる。

まずは、表示をどの程度残すか。TeraTermやWindowsTerminalでもスクロールバッファ行数や履歴のサイズとして指定する項目。
これを設定できないと際限なく表示が増えてしまうので。
これを実現するため、表示内容をdequeに保存し、新規行を追加した際にあふれた分を自動的に破棄するようにしている。

また、テキストが表示領域からあふれた際に自動的にスクロールするようにするため、ラベルのtexture_sizeプロパティが変更された際に イベントハンドラupdate_label_sizeがコールされるように設定。

        self.label.bind(texture_size=self.update_label_size)

ここでラベルのサイズをテクスチャサイズに合わせて変更している。
また、このときラベルサイズがスクロールビューのサイズを超えた時、self.scroll_y0,0に設定することで 最下行を表示できるようにしている。
なお、ラベルサイズがスクロールビューのサイズ以下の時にself.scroll_y0,0にしてしまうと下付き表示になってしまうため、 この条件ではself.scroll_y1,0にしている。
ラベルサイズがスクロールビューのサイズ以上の時に常にself.scroll_y0,0にすると 以前の内容を確認するためにスクロールしている状態で新しい行が表示されると最下行までスクロールしてしまうので、 0.0に設定するのはスクロールビューのサイズを超えた時だけにしている。

使い方

ScrollLabelクラスをインポートして使ってください。

from scrolllabel import ScrollLabel

設定できるプロパティはScrollViewのプロパティにrows(バッファ行数)を追加しています。
プロパティにrowsは初期化時にのみ変更可能です。 初期化後(実際は最初のテキスト出力後)は変更してもバッファ行数に反映されません。

テキストを追加するにはadd_text(text)を使用します。 引数endを指定することで行末文字を変更できます(デフォルトは\n)。
テキストを消去するにはclear_text()を使用します。

ソース

gistにupしたので、gistの埋め込みリンク貼っとく。
もしダウンロードしたいときは こちら からどうぞ。

また、gistには実際に使用する際の例(レイアウトに Kv language使用/python使用)も載せてあるのでよろしかったら見てください。