Bỏ qua để đến nội dung

🔢 Counter App

Xây dựng ứng dụng Counter với Declarative UI. ⏱️ 15 phút

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
  • Đã cài đặt Flet (pip install 'flet[all]')
  • Hiểu cơ bản về Components và use_state

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

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)
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)
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)
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)
  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
  • @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

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.