Skip to Content
Flet🔢 Counter App

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

  1. Step input - Cho phép chọn bước nhảy (1, 5, 10)
  2. Min/Max limit - Giới hạn khoảng cho phép
  3. History - Lưu lịch sử các giá trị
  4. Multiple counters - Nhiều counter độc lập

📝 Kiến thức ôn tập

  • @ft.component - Tạo component tái sử dụng
  • ft.use_state() - Quản lý state local
  • ft.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