こんにちは、森田です。
最近周りの人から Python でアプリ開発のできる Flet について教えてもらい、面白そうなのでチュートリアルをやってみました。
よかったら参考にしてみてください。
Flet とは
Flet は、フロントエンド開発の経験がなくても、簡単に Web、デスクトップ、モバイル アプリケーションを開発できるフレームワークです。
開発はPythonで行うことができ、内部的には、Flutter を利用しているようです。
標準でウィジェットが用意されているため、フロントの開発を行うことなく、少ない労力で、アプリとして動作させることができます。
Python で複雑すぎないアプリを作りたい場合にピッタリのフレームワークとなります。
やってみた
本記事では、チュートリアルに従って、電卓アプリを作ってみます。
なお、本記事では、Mac Python 3.8.13にて行います。
ライブラリのインストール
まずは、Fletのインストールを行います。以下のようにpipを使ってインストールを行います。
pip install flet
ボタンの作成
電卓のボタンを作成していきます。
ElevatedButtonを利用することで、作成可能です。
以下のコードでは、電卓の各ボタンを作成しております。
text引数に指定した文字列がボタン内に表示されます。
button_test.py
import flet as ft
def main(page: ft.Page):
page.title = "Calc App"
result = ft.Text(value="0")
page.add(
result,
ft.ElevatedButton(text="AC"),
ft.ElevatedButton(text="+/-"),
ft.ElevatedButton(text="%"),
ft.ElevatedButton(text="/"),
ft.ElevatedButton(text="7"),
ft.ElevatedButton(text="8"),
ft.ElevatedButton(text="9"),
ft.ElevatedButton(text="*"),
ft.ElevatedButton(text="4"),
ft.ElevatedButton(text="5"),
ft.ElevatedButton(text="6"),
ft.ElevatedButton(text="-"),
ft.ElevatedButton(text="1"),
ft.ElevatedButton(text="2"),
ft.ElevatedButton(text="3"),
ft.ElevatedButton(text="+"),
ft.ElevatedButton(text="0"),
ft.ElevatedButton(text="."),
ft.ElevatedButton(text="="),
)
ft.app(target=main)
実行結果
通常のPythonスクリプトのように実行すると、ウィンドウが開き、以下のようにボタンが表示されます。
python button_test.py
レイアウト調整
作成したボタンを電卓のようなレイアウトに変更します。
ft.Rowを使って行ごとの要素を並べていきます。
import flet as ft
def main(page: ft.Page):
page.title = "Calc App"
result = ft.Text(value="0")
page.add(
ft.Row(controls=[result]),
ft.Row(
controls=[
ft.ElevatedButton(text="AC"),
ft.ElevatedButton(text="+/-"),
ft.ElevatedButton(text="%"),
ft.ElevatedButton(text="/"),
]
),
ft.Row(
controls=[
ft.ElevatedButton(text="7"),
ft.ElevatedButton(text="8"),
ft.ElevatedButton(text="9"),
ft.ElevatedButton(text="*"),
]
),
ft.Row(
controls=[
ft.ElevatedButton(text="4"),
ft.ElevatedButton(text="5"),
ft.ElevatedButton(text="6"),
ft.ElevatedButton(text="-"),
]
),
ft.Row(
controls=[
ft.ElevatedButton(text="1"),
ft.ElevatedButton(text="2"),
ft.ElevatedButton(text="3"),
ft.ElevatedButton(text="+"),
]
),
ft.Row(
controls=[
ft.ElevatedButton(text="0"),
ft.ElevatedButton(text="."),
ft.ElevatedButton(text="="),
]
),
)
ft.app(target=main)
実行結果
デザインのカスタマイズ
ボタンの色変更などを行います。
bgcolorやcolorで色変更を行います。
import flet
from flet import (
Column,
Container,
ElevatedButton,
Page,
Row,
Text,
border_radius,
colors,
)
def main(page: Page):
page.title = "Calc App"
result = Text(value="0", color=colors.WHITE, size=20)
page.add(
Container(
width=300,
bgcolor=colors.BLACK,
border_radius=border_radius.all(20),
padding=20,
content=Column(
controls=[
Row(controls=[result], alignment="end"),
Row(
controls=[
ElevatedButton(
text="AC",
bgcolor=colors.BLUE_GREY_100,
color=colors.BLACK,
expand=1,
),
ElevatedButton(
text="+/-",
bgcolor=colors.BLUE_GREY_100,
color=colors.BLACK,
expand=1,
),
ElevatedButton(
text="%",
bgcolor=colors.BLUE_GREY_100,
color=colors.BLACK,
expand=1,
),
ElevatedButton(
text="/",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
),
]
),
Row(
controls=[
ElevatedButton(
text="7",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="8",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="9",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="*",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
),
]
),
Row(
controls=[
ElevatedButton(
text="4",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="5",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="6",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="-",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
),
]
),
Row(
controls=[
ElevatedButton(
text="1",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="2",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="3",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="+",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
),
]
),
Row(
controls=[
ElevatedButton(
text="0",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=2,
),
ElevatedButton(
text=".",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
),
ElevatedButton(
text="=",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
),
]
),
]
),
)
)
flet.app(target=main)
実行結果
以下のように良い感じに電卓アプリケーションが表示されます。
ボタン押下時のイベント処理
見た目の作成は完了しましたので、再度に電卓として利用できるように、計算の処理を追加します。
ft.ElevatedButtonでは、on_clickにボタンを押下時に実行する関数を指定することができます。
import flet
from flet import (
Column,
Container,
ElevatedButton,
Page,
Row,
Text,
UserControl,
border_radius,
colors,
)
class CalculatorApp(UserControl):
def build(self):
self.reset()
self.result = Text(value="0", color=colors.WHITE, size=20)
# application's root control (i.e. "view") containing all other controls
return Container(
width=300,
bgcolor=colors.BLACK,
border_radius=border_radius.all(20),
padding=20,
content=Column(
controls=[
Row(controls=[self.result], alignment="end"),
Row(
controls=[
ElevatedButton(
text="AC",
bgcolor=colors.BLUE_GREY_100,
color=colors.BLACK,
expand=1,
on_click=self.button_clicked,
data="AC",
),
ElevatedButton(
text="+/-",
bgcolor=colors.BLUE_GREY_100,
color=colors.BLACK,
expand=1,
on_click=self.button_clicked,
data="+/-",
),
ElevatedButton(
text="%",
bgcolor=colors.BLUE_GREY_100,
color=colors.BLACK,
expand=1,
on_click=self.button_clicked,
data="%",
),
ElevatedButton(
text="/",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="/",
),
],
),
Row(
controls=[
ElevatedButton(
text="7",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="7",
),
ElevatedButton(
text="8",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="8",
),
ElevatedButton(
text="9",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="9",
),
ElevatedButton(
text="*",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="*",
),
]
),
Row(
controls=[
ElevatedButton(
text="4",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="4",
),
ElevatedButton(
text="5",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="5",
),
ElevatedButton(
text="6",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="6",
),
ElevatedButton(
text="-",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="-",
),
]
),
Row(
controls=[
ElevatedButton(
text="1",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="1",
),
ElevatedButton(
text="2",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="2",
),
ElevatedButton(
text="3",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="3",
),
ElevatedButton(
text="+",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="+",
),
]
),
Row(
controls=[
ElevatedButton(
text="0",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=2,
on_click=self.button_clicked,
data="0",
),
ElevatedButton(
text=".",
bgcolor=colors.WHITE24,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data=".",
),
ElevatedButton(
text="=",
bgcolor=colors.ORANGE,
color=colors.WHITE,
expand=1,
on_click=self.button_clicked,
data="=",
),
]
),
],
),
)
def button_clicked(self, e):
data = e.control.data
if self.result.value == "Error" or data == "AC":
self.result.value = "0"
self.reset()
elif data in ("1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "."):
if self.result.value == "0" or self.new_operand == True:
self.result.value = data
self.new_operand = False
else:
self.result.value = self.result.value + data
elif data in ("+", "-", "*", "/"):
self.result.value = self.calculate(
self.operand1, float(self.result.value), self.operator
)
self.operator = data
if self.result.value == "Error":
self.operand1 = "0"
else:
self.operand1 = float(self.result.value)
self.new_operand = True
elif data in ("="):
self.result.value = self.calculate(
self.operand1, float(self.result.value), self.operator
)
self.reset()
elif data in ("%"):
self.result.value = float(self.result.value) / 100
self.reset()
elif data in ("+/-"):
if float(self.result.value) > 0:
self.result.value = "-" + str(self.result.value)
elif float(self.result.value) < 0:
self.result.value = str(
self.format_number(abs(float(self.result.value)))
)
self.update()
def format_number(self, num):
if num % 1 == 0:
return int(num)
else:
return num
def calculate(self, operand1, operand2, operator):
if operator == "+":
return self.format_number(operand1 + operand2)
elif operator == "-":
return self.format_number(operand1 - operand2)
elif operator == "*":
return self.format_number(operand1 * operand2)
elif operator == "/":
if operand2 == 0:
return "Error"
else:
return self.format_number(operand1 / operand2)
def reset(self):
self.operator = "+"
self.operand1 = 0
self.new_operand = True
def main(page: Page):
page.title = "Calc App"
# create application instance
calc = CalculatorApp()
# add application's root control to the page
page.add(calc)
flet.app(target=main)
実行結果
実際に実行すると、以下のようにボタン押下時に計算を行い、計算結果の表示ができるようになります。
さいごに
今回は、Fletを使ってアプリ開発を行ってみましたが、非常に簡単に作成できます。
ウィジェットも豊富に用意されているため、素早くアプリ開発を行いたい場合には、とても便利です。
今までPythonを使ったことのある方は、すぐに活用することができますので、ぜひお試しください。