家計簿アプリを作成する⑤【ログイン画面作成(UI)】

Flet

ログイン画面作成(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,
            )

全体コード(GitHub)

household_account_book/display/login.py at main · SakumaTakayuki/household_account_book
Contribute to SakumaTakayuki/household_account_book development by creating an account on GitHub.