CircuitPython displayioライブラリの使い方 (5/5)

AdafruitのLearning Guideの非公式日本語訳です。
英語独特の言い回しを可能な限り日本語的な表現に直していますが、不自然に感じる部分も残っていますことを何卒ご容赦ください。

ユーザーインターフェースの作り方

displayioには、いくつかのユーザーインターフェース(UI)要素が用意されています。これらを組み合わせることで、電卓のような楽しいアプリケーションを作ることができます。

ディスプレイを初期化する

ディスプレイを搭載しているボードでは、画面は自動的に初期化されます。これを参照するには、boardをインポートして、内蔵のディスプレイ参照に割り当てるだけです。

import board
 
display = board.DISPLAY

ディスプレイが内蔵されていないボードでは、CircuitPythonのページを参照して特定のディスプレイを初期化することをお勧めします。その後、ディスプレイドライバの初期化で返される出力にディスプレイを割り当てます。例えば、ILI9341ディスプレイの場合、以下のようになりますが、ピンによって異なる場合があります。

import board
import displayio
import adafruit_ili9341
 
displayio.release_displays()
 
spi = board.SPI()
tft_cs = board.D9
tft_dc = board.D10
 
display_bus = displayio.FourWire(
    spi, command=tft_dc, chip_select=tft_cs, reset=board.D6
)
display = adafruit_ili9341.ILI9341(display_bus, width=320, height=240)

グループ

グループは、displayioが描画に必要なすべての要素を把握するための手段です。サブグループはグループの中に入れることができますが、少なくとも1つのメイングループがなければなりません。このページのすべての要素を表示するためには、まずdisplayioをインポートする必要がありますので、それがコードの先頭にあることを確認しておきましょう。

import displayio

また、メイングループとして使用するグループを1つ以上作成する必要があります。

my_display_group = displayio.Group(max_size=25)
display.show(my_display_group)

シェイプ

この図形は、adafruit_display_shapesライブラリの一部です。この記事を書いている時点では、3つのシェイプがあります。これらは、displayioを使って特定の形状のビットマップを生成することで動作します。

長方形(Rectangle)

長方形は、最も基本的な形状です。塗りつぶしたり、アウトライン化したり、あるいはその両方を行うことができます。

角丸長方形(Rounded Rectangle)

角丸長方形は、もう少し複雑で、4本の線と1/4円の角で構成されています。

円(Circle)

円は、丸みを帯びた長方形をベースに、幅や高さを指定せずに四隅のみを描画します。

三角形(Triangle)

三角形では、3つの座標を入力すると、それらの頂点の間にアウトラインを描くか、塗りつぶすか、またはその両方を行います。

シェイプを使用するには、まずコードの先頭に使用したいシェイプをインポートする必要があります。例えば、すべてのシェイプを個別にインポートする場合は、以下のように追加します。

from adafruit_display_shapes.rect import Rect
from adafruit_display_shapes.circle import Circle
from adafruit_display_shapes.roundrect import RoundRect
from adafruit_display_shapes.triangle import Triangle

次に、長方形を描く場合は以下のようにします。

rect = Rect(0, 0, 80, 40, fill=0x00FF00)

円を描く場合は以下のようにします。

circle = Circle(100, 100, 20, fill=0x00FF00, outline=0xFF00FF)

三角形を描く場合は以下のようにします。

triangle = Triangle(170, 50, 120, 140, 210, 160, fill=0x00FF00, outline=0xFF00FF)

角丸長方形を描く場合は以下のようにします。

roundrect = RoundRect(50, 100, 40, 80, 10, fill=0x0, outline=0xFF00FF, stroke=3)

最後にこれらのシェイプをグループに追加します。

my_display_group.append(rect)
my_display_group.append(circle)
my_display_group.append(triangle)
my_display_group.append(roundrect)

フォント

フォントについては、いくつかの選択肢があります。カスタムフォントファイルを作成または入手し、それをラベルとして使用することができます。カスタムビットマップフォントを使用したくない場合は、内蔵のターミナルフォントを使用することができます。

内蔵ターミナルフォント

内蔵のターミナルフォントは少しギザギザしていますが、少なくとも別のファイルを用意する必要は必要ありません。

写真は、PyBadger Event Badgeガイドで使用したターミナルフォントの表示例です。

内蔵のターミナルフォントを使うには、まずファイルの先頭にimport文を追加して、terminalioをインポートする必要があります。

import terminalio

そして、UI要素にterminalioフォントを渡すだけです。例えば、ラベルの場合は、次のようにします。

my_label = Label(terminalio.FONT, text="My Label Text", color=BLACK)

ビットマップフォント

ビットマップフォントはadafruit_bitmap_fontライブラリを使用しており、別途BDF(Bitmap Distribution Format)ファイルが必要ですが、画面上ではきれいに見えます。アンチエイリアス処理をしていないので、フォントによっては少しギザギザして見えることもあります。

写真は、PyBadge Conference Badge With Unicode Fonts ガイドに掲載された例です。

ビットマップフォントを使用するには、まず、フォントのBDFファイルをCIRCUITPYドライブにコピーする必要があります。fontsフォルダを作成してその中にフォントを入れるのがオススメです。

次に、コードの先頭にimport文を追加して、bitmap_fontをインポートします。

from adafruit_bitmap_font import bitmap_font

その後、フォントインスタンスを作成します。たとえば、fonts フォルダに Arial-12.bdf という名前のフォントファイルがある場合、次のようなコードを使用します。

font = bitmap_font.load_font("/fonts/Arial-12.bdf")

そして、フォントのインスタンスをUI要素に渡すだけです。例えば、ラベルの場合は以下のようになります。

my_label = Label(font, text="My Label Text", color=BLACK)

ラベル

ラベルには、adafruit_display_textライブラリが必要です。このライブラリには、フォントを渡す必要があります。これは、Terminal FontまたはCustom Fontのいずれかです。これにより、テキストを表示し、それをdisplayioグループに配置することができます。フォントの項で紹介したカンファレンスバッジでは、ラベルが大いに活用されています。

ラベルを作成するには、まず、必要なライブラリをコードの先頭にimport文で書きます。

from adafruit_display_text.label import Label

そしてラベルを作成します。

my_label = Label(terminalio.FONT, text="My Label Text", color=BLACK)

最後に、ラベルをdisplayioグループに追加します。これはメイングループでもサブグループでも構いません。

my_display_group.append(my_label)

ボタン

ボタンは adafruit_button ライブラリを使用しており、adafruit_display_shapes、adafruit_label、adafruit_touchscreen ライブラリの上に構築されています。ボタンは基本的にシェイプとラベルが一緒になったもので、色の反転だけでなく、押した状態も扱うことができます。

ボタンを使用するには、必要なライブラリをファイルの先頭に追加する必要があります。

from adafruit_button import Button
import adafruit_touchscreen

次に、ボタンを作成します。たくさんのオプションがあるので、ボタンライブラリで提供されている例を見て、いろいろなことができるということを理解してください。

my_button = Button(x=20, y=20, width=80, height=40,
                   label="My Button", label_font=terminalio.FONT)

フォントは必須ですが、ここでもビルトインフォントかカスタムフォントのどちらかを用意してください。最後に、グループに追加します。

my_display_group.append(my_button)

シンプルなテストの例では、さまざまなバリエーションを示しています。

画像

今回の電卓プロジェクトでは使用していませんが、画像も利用できます。displayioで画像を表示するには、いくつかの方法があります。

ImageLoadライブラリ

Imageloadはadafruit_imageloadライブラリのメインクラスで、ビットマップのデコードと表示を簡単に行うことができます。現時点では、インデックス付きの8ビットビットのビットマップをデコードすることしかできません。これを使用するには、まずファイルの先頭にライブラリをインクルードします。

import adafruit_imageload

次に、画像からビットマップとパレットを生成します。

my_bitmap, my_palette = adafruit_imageload.load("/my_bitmap.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)

さらに、BitmapとPaletteからTileGridを作成します。

my_tilegrid = displayio.TileGrid(my_bitmap, pixel_shader=my_palette)

最後に、TileGridをdisplay groupに追加します。

my_display_group.append(my_tilegrid)

OnDiskBitmap

OnDiskBitmapはdisplayioから直接利用でき、使い方はとても簡単です。まず、画像ファイルをリードモードとバイナリモードで開き、ビットマップを作成します。その柔軟性とメモリ使用量の少なさから、この方法が推奨されています。

my_bitmap = displayio.OnDiskBitmap(open("/my_bitmap.bmp", "rb"))

次に、自動色変換機能を使って、画像からTileGridを作成します。

my_tilegrid = displayio.TileGrid(my_bitmap, pixel_shader=displayio.ColorConverter())

最後に、TileGridをdisplay groupに追加します。

my_display_group.append(my_tilegrid)

電卓のUI

PyPortalを使った電卓では、矩形、ラベル、ボタンの各要素を使用します。

Follow me on Twitter