flet 星空登录界面

386 阅读1分钟
import flet as ft
import random
import asyncio


def get_random_pos() -> int:
    return random.randint(1, 1280)


def get_random_color() -> str:
    colors = ['blue', 'white']
    return random.choice(colors)


def get_random_offset() -> int:
    return random.randint(1, 5)


def get_random_wait() -> int:
    return random.randrange(500, 700, 100)


# 设置背景动画
class Thing(ft.Container):

    def __init__(self):
        color = get_random_color()
        super().__init__(
            left=get_random_pos(),
            top=get_random_pos(),
            width=2.5,
            height=2.5,
            shape=ft.BoxShape(ft.BoxShape.CIRCLE),
            bgcolor=color,
            opacity=0,
            offset=ft.transform.Offset(0, 0),
            shadow=ft.BoxShadow(spread_radius=20, blur_radius=100, color=color)
        )
        self.wait = get_random_wait()
        self.animate_opacity = ft.Animation(self.wait, ft.AnimationCurve.EASE)
        self.animate_offset = ft.Animation(self.wait, ft.AnimationCurve.EASE)

    async def animate_thing(self, event=None):
        self.opacity = 1
        self.offset = ft.transform.Offset(get_random_offset() ** 2, get_random_offset() ** 2)
        self.update()
        await asyncio.sleep(self.wait / 1000)
        self.opacity = 0
        self.offset = ft.transform.Offset(get_random_offset() ** 2, get_random_offset() ** 2)
        self.update()
        await asyncio.sleep(self.wait / 1000)
        await self.animate_thing()


# 输入框
# input_style = {
#     'height': 38,
#     'fou'
# }


class Input(ft.TextField):
    def __init__(self, password: bool) -> None:
        super().__init__(
            height=38,
            focused_border_color=ft.colors.BLUE,
            border_radius=5,
            cursor_height=16,
            cursor_color=ft.colors.WHITE,
            content_padding=10,
            border_width=1.5,
            text_size=12,
            password=password
        )


# 登录按钮
class LoginButton(ft.ElevatedButton):
    def __init__(self, text: str):
        super().__init__(
            expand=True,
            bgcolor=ft.colors.BLUE,
            style=ft.ButtonStyle(shape={'': ft.RoundedRectangleBorder(radius=5)}),
            color=ft.colors.WHITE,
            text=text
        )


class Body(ft.Container):
    def __init__(self):
        super().__init__(
            width=400,
            padding=15,
            bgcolor=ft.colors.with_opacity(0.045, ft.colors.WHITE),
            border_radius=10,
            shadow=ft.BoxShadow(spread_radius=20, blur_radius=45, color=ft.colors.with_opacity(0.45, ft.colors.BLACK))
        )
        self.username = Input(password=False)
        self.password = Input(password=True)

        self.content = ft.Column(
            controls=[
                ft.Divider(height=10, color=ft.colors.TRANSPARENT),
                ft.Text('用户名', size=10),
                self.username,
                ft.Divider(height=10, color=ft.colors.TRANSPARENT),
                ft.Text('密  码', size=10),
                self.password,
                ft.Divider(height=15, color=ft.colors.TRANSPARENT),
                ft.Row(controls=[LoginButton('登录')])
            ]
        )


def main(page: ft.Page):
    page.horizontal_alignment = ft.MainAxisAlignment.CENTER
    page.vertical_alignment = ft.alignment.center
    page.theme_mode = ft.ThemeMode.DARK
    page.padding = 0
    page.window_center()
    print(page.window_width)

    # 背景
    background = ft.Stack(
        expand=True,
        controls=[Thing() for _ in range(100)]
    )
    stack = ft.Stack(
        expand=True,
        controls=[background, ft.Column(
            alignment=ft.MainAxisAlignment.CENTER,
            # horizontal_alignment=ft.alignment.center,
            controls=[
                ft.Row(
                    alignment=ft.MainAxisAlignment.CENTER,
                    controls=[Body()]
                )
            ]
        )]
    )
    page.add(stack)
    page.update()

    async def run():
        await asyncio.gather(
            *(item.animate_thing() for item in background.controls)
        )

    asyncio.run(run())


if __name__ == '__main__':
    ft.app(main)

image.png