Mini Project: Counter App 🔢
Xây dựng ứng dụng Counter với Declarative UI. ⏱️ 15 phút
🎯 Mục tiêu
Tạo ứng dụng đếm số với:
- Nút tăng (+) và giảm (-)
- Hiển thị số hiện tại
- Nút reset về 0
- UI đẹp với Card và styling
📋 Yêu cầu
- Đã cài đặt Flet (
pip install 'flet[all]') - Hiểu cơ bản về Components và use_state
🚀 Bắt đầu
Bước 1: Tạo file project
Tạo file counter_app.py:
import flet as ft
def main(page: ft.Page):
page.title = "Counter App"
page.add(ft.Text("Hello"))
ft.run(main)Chạy thử: flet run counter_app.py
Bước 2: Tạo Counter Component
import flet as ft
@ft.component
def Counter():
count, set_count = ft.use_state(0)
return ft.Text(str(count), size=48)
def main(page: ft.Page):
page.title = "Counter App"
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.add(Counter())
ft.run(main)Bước 3: Thêm các nút điều khiển
import flet as ft
@ft.component
def Counter():
count, set_count = ft.use_state(0)
return ft.Column([
ft.Text(str(count), size=72, weight=ft.FontWeight.BOLD),
ft.Row([
ft.IconButton(
ft.Icons.REMOVE_CIRCLE,
icon_size=40,
icon_color=ft.Colors.RED,
on_click=lambda _: set_count(count - 1),
),
ft.IconButton(
ft.Icons.ADD_CIRCLE,
icon_size=40,
icon_color=ft.Colors.GREEN,
on_click=lambda _: set_count(count + 1),
),
], alignment=ft.MainAxisAlignment.CENTER),
], horizontal_alignment=ft.CrossAxisAlignment.CENTER)
def main(page: ft.Page):
page.title = "Counter App"
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.add(Counter())
ft.run(main)Bước 4: Thêm nút Reset và styling
import flet as ft
@ft.component
def Counter():
count, set_count = ft.use_state(0)
# Xác định màu dựa trên giá trị
def get_color():
if count > 0:
return ft.Colors.GREEN
elif count < 0:
return ft.Colors.RED
return ft.Colors.GREY
return ft.Card(
content=ft.Container(
content=ft.Column([
ft.Text("COUNTER", size=16, color=ft.Colors.GREY_500),
ft.Text(
str(count),
size=72,
weight=ft.FontWeight.BOLD,
color=get_color(),
),
ft.Row([
ft.IconButton(
ft.Icons.REMOVE_CIRCLE,
icon_size=50,
icon_color=ft.Colors.RED_400,
tooltip="Giảm",
on_click=lambda _: set_count(count - 1),
),
ft.IconButton(
ft.Icons.REFRESH,
icon_size=40,
icon_color=ft.Colors.GREY_400,
tooltip="Reset",
on_click=lambda _: set_count(0),
),
ft.IconButton(
ft.Icons.ADD_CIRCLE,
icon_size=50,
icon_color=ft.Colors.GREEN_400,
tooltip="Tăng",
on_click=lambda _: set_count(count + 1),
),
], alignment=ft.MainAxisAlignment.CENTER),
], horizontal_alignment=ft.CrossAxisAlignment.CENTER, spacing=10),
padding=40,
),
elevation=5,
)
def main(page: ft.Page):
page.title = "Counter App"
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.bgcolor = ft.Colors.GREY_100
page.add(Counter())
ft.run(main)✅ Code hoàn chỉnh
import flet as ft
@ft.component
def Counter():
count, set_count = ft.use_state(0)
def get_color():
if count > 0:
return ft.Colors.GREEN
elif count < 0:
return ft.Colors.RED
return ft.Colors.GREY_700
return ft.Card(
content=ft.Container(
content=ft.Column([
ft.Text("COUNTER", size=14, color=ft.Colors.GREY_500, weight=ft.FontWeight.W_500),
ft.Container(
content=ft.Text(
str(count),
size=80,
weight=ft.FontWeight.BOLD,
color=get_color(),
),
padding=ft.padding.symmetric(vertical=20),
),
ft.Row([
ft.FilledTonalButton(
content=ft.Icon(ft.Icons.REMOVE, size=30),
style=ft.ButtonStyle(shape=ft.CircleBorder(), padding=15),
on_click=lambda _: set_count(count - 1),
),
ft.OutlinedButton(
content=ft.Icon(ft.Icons.REFRESH, size=24),
style=ft.ButtonStyle(shape=ft.CircleBorder(), padding=10),
on_click=lambda _: set_count(0),
),
ft.FilledTonalButton(
content=ft.Icon(ft.Icons.ADD, size=30),
style=ft.ButtonStyle(shape=ft.CircleBorder(), padding=15),
on_click=lambda _: set_count(count + 1),
),
], alignment=ft.MainAxisAlignment.CENTER, spacing=20),
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
padding=50,
),
elevation=8,
)
def main(page: ft.Page):
page.title = "Counter App"
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.bgcolor = ft.Colors.BLUE_GREY_50
page.add(Counter())
ft.run(main)🎯 Thử thách mở rộng
- Step input - Cho phép chọn bước nhảy (1, 5, 10)
- Min/Max limit - Giới hạn khoảng cho phép
- History - Lưu lịch sử các giá trị
- Multiple counters - Nhiều counter độc lập
📝 Kiến thức ôn tập
@ft.component- Tạo component tái sử dụngft.use_state()- Quản lý state localft.Card,ft.Container- Styling UI- Event handlers với lambda
⏭️ Tiếp theo
Tuyệt! Tiếp tục với Mini Project: Todo List để xây dựng ứng dụng phức tạp hơn.
Last updated on