ログイン画面作成(UI)
登録されているユーザーだけが家計簿アプリを使用できるように、ログイン画面(UI)を作成する
ログイン画面


Loginクラス
概要
通常fletでの画面の作成はViewで作成するが、自作コントロールのMy_Control.MyViewを使用する
My_Control.MyViewでは、Viewを継承し、__init__で「bgcolor=ft.Colors.LIGHT_BLUE_50」とすることで、背景色を設定している
エラーメッセージを表示するコントロールは、自作コントロールのMy_Control.Msgboxを使用する
AlertDialogでメッセージを表示することもできるが、My_Control.Msgboxのインスタンス時にメッセージIDとメッセージ内容を渡すだけでAlertDialogコントロールを作成できるようにしている
自作コントロールを使用することで、元のコントロールでの設定が省略され、デザインの統一化できる
(ソースは下に記載)
【Loginクラスのイニシャライザ】
・ログインアダプターのインスタンス化
・画面のコントロール・ウィンドウの設定
を行う
【ログインボタン】
ログインボタンを押した時
・ユーザーID
・パスワード
が空欄の場合、エラーメッセージを表示する


ユーザーIDとパスワードが入力されている場合
・ログインアダプターにユーザーID、パスワードを渡し、ログイン認証を行う
・ログインアダプターからユーザー情報を受け取る
ログインアダプターから受け取った情報にユーザー情報がない場合
・エラーメッセージを表示する

DB操作時に例外エラーが発生した場合
・例外エラーメッセージを表示する


ログインアダプターから受け取った情報にユーザー情報がある場合
・pageのdataにユーザー情報を設定する
・家計簿一覧画面を表示する
pageのdataにユーザー情報を設定することで、すべての画面でログインしたユーザーの情報を参照することができる

ソースコード
import flet as ft
from db.login_adapter import Login_Adapter
from common.my_control import My_Control
from common.message import Message
# ログイン画面
class Login(My_Control.MyView):
def __init__(self, arg_page: ft.Page):
# ログインアダプターをインスタンス化
self.login_adapter = Login_Adapter()
# 画面ラベル作成
self.display_label = ft.Container(
content=ft.Text(
"ログイン",
size=30,
weight=ft.FontWeight.BOLD,
),
alignment=ft.alignment.center,
)
# ユーザーID入力エリア作成
self.id_TextField = ft.TextField(
label=ft.Text("ユーザーID", size=18), bgcolor=ft.Colors.WHITE, text_size=18
)
# パスワード入力エリア作成
# password=Trueで入力した値がマスクされるように設定
self.password_TextField = ft.TextField(
label=ft.Text("パスワード", size=18),
password=True,
bgcolor=ft.Colors.WHITE,
text_size=18,
)
# ログインボタン作成
# ボタンクリック時にlogin_submit_clickを呼び出す
self.submit = ft.FilledButton(
content=ft.Text("ログイン", size=18),
width=100,
height=40,
disabled=False,
on_click=lambda e: Login.login_submit_click(self),
)
# controlに作成したコントロールを追加する
# ユーザーID入力エリア、パスワード入力エリア、ログインボタンは縦並びかつ枠線内にあるデザインにするため
# ft.Container内にft.Column(縦並び)で配置し、ft.Containerに枠線を設定する
control = [
self.display_label,
ft.Container(
content=ft.Column(
controls=[
self.id_TextField,
self.password_TextField,
self.submit,
]
),
border=ft.border.all(2.0, ft.Colors.BLACK),
padding=20,
),
]
# ウィンドウサイズと表示位置を設定
arg_page.window.width = 505
arg_page.window.height = 320
arg_page.window.center()
# "/login"が呼び出された時にcontrolが表示されるように設定
super().__init__("/login", control)
def login_submit_click(self):
"""
ログインボタンクリックイベント
"""
# 画面を非活性にする
self.disabled = True
self.update()
# idにユーザーIDを代入する
id = self.controls[1].content.controls[0].value
# idの入力値チェック
if id == "":
msg = My_Control.Msgbox(
"HAB005C",
Message.Message_Box.HAB005C.format("ユーザーID"),
)
# 自作コントロールのメッセージボックスをログイン画面上に表示する
self.page.open(msg)
# 画面を活性にする
self.disabled = False
self.update()
return
# passwordにパスワードを代入する
password = self.controls[1].content.controls[1].value
# passwordの入力値チェック
if password == "":
msg = My_Control.Msgbox(
"HAB005C",
Message.Message_Box.HAB005C.format("パスワード"),
)
# 自作コントロールのメッセージボックスをログイン画面上に表示する
self.page.open(msg)
# 画面を活性にする
self.disabled = False
self.update()
return
# ログインアダプターを使用し、ログイン認証を行う
# user_rowにはユーザー情報、ログイン失敗メッセージが代入されている
user_row = self.login_adapter.login(
id,
password,
)
# user_row.return_rowにユーザー情報がない場合
if user_row.return_row is None:
# user_row.return_message_boxに代入されたメッセージ情報を
# 自作コントロールのメッセージボックスに渡しインスタンス化
msg = My_Control.Msgbox(
user_row.return_message_box.message_id,
user_row.return_message_box.message_text,
)
# 自作コントロールのメッセージボックスをログイン画面上に表示する
self.page.open(msg)
# 画面を活性にする
self.disabled = False
self.update()
else:
# self.page.dataにユーザー情報を代入し、どの画面でもユーザー情報を参照できるようにする
self.page.data = user_row.return_row
# 家計簿一覧画面を表示する
self.page.go("/HAB_list")
My_Control.MyViewクラス
FletのViewを継承し、背景色を「bgcolor=ft.Colors.LIGHT_BLUE_50」とすることで統一する
import flet as ft
class My_Control:
# ビュー
class MyView(ft.View):
def __init__(
self,
route=None,
controls=None,
appbar=None,
bottom_appbar=None,
floating_action_button=None,
floating_action_button_location=None,
navigation_bar=None,
drawer=None,
end_drawer=None,
vertical_alignment=None,
horizontal_alignment=None,
spacing=None,
padding=None,
bgcolor=ft.Colors.LIGHT_BLUE_50,
decoration=None,
foreground_decoration=None,
can_pop=None,
on_confirm_pop=None,
scroll=None,
auto_scroll=None,
fullscreen_dialog=None,
on_scroll_interval=None,
on_scroll=None,
adaptive=None,
):
super().__init__(
route,
controls,
appbar,
bottom_appbar,
floating_action_button,
floating_action_button_location,
navigation_bar,
drawer,
end_drawer,
vertical_alignment,
horizontal_alignment,
spacing,
padding,
bgcolor,
decoration,
foreground_decoration,
can_pop,
on_confirm_pop,
scroll,
auto_scroll,
fullscreen_dialog,
on_scroll_interval,
on_scroll,
adaptive,
)
My_Control.Msgboxクラス
FletのAlertDialogを継承し、メッセージIDとメッセージ内容を受け取りインスタンス化することで、デザインを統一したAlertDialogを作成できる
__ini__内で、受け取ったメッセージIDをtitleに、メッセージ内容をcontentに設定している
import flet as ft
class My_Control:
# メッセージボックス
class Msgbox(ft.AlertDialog):
def __init__(self, arg_title, arg_content):
"""
メッセージボックス作成
引数
arg_title:メッセージID
arg_content:メッセージ内容
"""
super().__init__(
modal=True,
title=ft.Text(
f"【{arg_title}】",
size=18,
weight=ft.FontWeight.BOLD,
),
content=ft.Text(f"{arg_content}", size=18),
actions=[
ft.TextButton("はい", on_click=lambda e: self.page.close(self)),
],
actions_alignment=ft.MainAxisAlignment.END,
)