2023年01月17日
新年あけましておめでとうございます。
2023年最初の社員ブログ投稿(予定)です。
さて、今回はFletを用いたクロスプラットフォームアプリケーション開発について紹介したいと思います。
FletはPythonでWeb, Mobile, Desktopのアプリケーションをフロントエンドの経験不要で作成できるフレームワークです。
主な特徴として、以下が挙げられます。
Fletは現在v0.3.2 (2023年1月16日現在) とメジャーバージョン0ではあるものの、意欲的なロードマップが公開されており、今後のアップデートにもかなり期待が持てます。
PythonによるGUIアプリ開発の選択肢として、Pythonの標準ライブラリであるTkinterや、以前弊社ブログにて紹介があったKivyなどがありますが、今回紹介するFletもFlutterベースのアプリ開発フレームワークとして有力な選択肢になるのではないかと思います。
Python3.7以降の開発環境があれば、fletモジュールをインストールするだけですぐに開発をはじめられます。
fletモジュールはPyPIに登録されており、pipを用いて簡単にインストール可能です。
pip install flet
さっそく、最初のFletアプリを作ってみましょう。
基本的なFletアプリの構成は下記のようになっています。
import flet as ft
def main(page: ft.Page):
pass
ft.app(target=main)
ft.app()の呼び出しで新たなユーザーセッションを待ち受けるようになります。
targetで指定したmain関数がアプリのエントリーポイントとなり、ユーザーセッションごとにPageと呼ばれるコンテナが作成されます。
FletではPageにControl(と呼ばれるウィジェット)を追加/削除したり、Controlのプロパティを更新することでアプリのUIを構築します。
上記のコードを実行すると、空白のPageを持つFletアプリがOSのネイティブウィンドウで起動します。
また、下記のようにviewにft.WEB_BROWSERを指定して実行すると、Fletアプリがウェブブラウザで起動します。
ft.app(target=main, view=ft.WEB_BROWSER)
FletアプリにおけるPageはControlと呼ばれるウィジェットのコンテナであると説明しましたが、具体的にはPageのプロパティであるcontrolsにControlを追加/削除することで表示するControlを制御しています。
controlsは表示されるControlのリストになっており、以下のようにして追加を行います。
page.controls.append(ft.Text('Hello'))
page.update()
page.add(ft.Text('Hello'))
ft.Text()は、その名の通りテキストを表示するためのControlで、上記の例では”Hello”と表示するControlになっています。
ここまでのコードと実行結果は以下のようになっているかと思います。
import flet as ft
def main(page: ft.Page):
page.add(ft.Text("Hello"))
ft.app(target=main)
Fletではft.Textの他にも、すぐに利用可能なControlが多数用意されています。
また、UserControlを用いることで既存のControlを組み合わせて独自のプロパティ、メソッドを持つControlを定義することも可能です。
FletにおけるControlはPythonのクラスで実装されており、buildメソッドにて表示するControlのインスタンスを返します。
独自のUserControlを定義する場合は、以下のようにUserControlを継承するクラスとして定義してbuildメソッドを実装します。
import flet as ft
class MyControl(ft.UserControl):
def build(self):
return ft.Card(
content=ft.Container(
content=ft.Row(
[
ft.CircleAvatar(content=ft.Text("UN"), bgcolor=ft.colors.DEEP_PURPLE_300),
ft.Column(
controls=[
ft.Text("UserName", style=ft.TextThemeStyle.TITLE_MEDIUM),
ft.Text("email@example.com", color=ft.colors.BLACK38),
],
alignment=ft.MainAxisAlignment.SPACE_AROUND,
),
]
),
width=400,
padding=16,
)
)
def main(page: ft.Page):
for _ in range(4):
page.add(MyControl())
ft.app(target=main)
さらに、コンストラクタやライフサイクルフックのようなメソッドを追加することも可能です。
試しに、OpenCVを用いてキャプチャされたカメラの映像を描画するControlを作成してみたいと思います。
import base64
import threading
from time import sleep
import cv2
import flet as ft
class CameraCaptureControl(ft.UserControl):
def __init__(self):
super().__init__()
self.capture = cv2.VideoCapture(0)
self.latency = 1 / self.capture.get(cv2.CAP_PROP_FPS)
def did_mount(self):
self.running = True
self.thread = threading.Thread(target=self.update_frame, args=(), daemon=True)
self.thread.start()
def will_unmount(self):
self.running = False
def update_frame(self):
while self.capture.isOpened() and self.running:
# TODO retvalのチェックとハンドリングを実装
retval, frame = self.capture.read()
retval, frame = cv2.imencode(".jpg", frame)
data = base64.b64encode(frame)
self.image_control.src_base64 = data.decode()
self.update()
sleep(self.latency)
def build(self):
self.image_control = ft.Image(
width=self.capture.get(cv2.CAP_PROP_FRAME_WIDTH),
height=self.capture.get(cv2.CAP_PROP_FRAME_HEIGHT),
fit=ft.ImageFit.FIT_WIDTH,
)
return self.image_control
既存のControlであるImageのプロパティを、取得したフレームに更新した後、UserControlのupdateメソッドを呼び出すことで描画が更新されています。
作成したFletアプリはPyInstallerを用いてデスクトップアプリとしてビルドしたり、WebSocketに対応したホスティングサービスを用いてWebアプリとしてデプロイすることが可能です。
今回は、Pythonのクロスプラットフォームアプリケーション開発フレームワークであるFletについて、概要をご紹介しました。
手早くきれいなGUIアプリを作成可能なFletは公式ドキュメントも読みやすく、開発環境の構築も容易だと感じました。
社内ツールやデモアプリの作成する際や、GUIアプリ作成に興味を抱いた方は、ぜひFletを試してみてください。
とりとめのない記事になってしまいましたが、お読みいただきありがとうございました。