Xử lý sự kiện trong Flet
Học cách xử lý các sự kiện người dùng như click, nhập liệu, hover… ⏱️ 15 phút
🎯 Mục tiêu
Nắm vững cách xử lý events với on_click, on_change, và các event handlers khác.
🖱️ on_click - Xử lý click
Trong Declarative UI, event handlers thay đổi state và UI tự động cập nhật:
import flet as ft
@ft.component
def ClickExample():
count, set_count = ft.use_state(0)
return ft.Column([
ft.Text(f"Clicked: {count} times"),
ft.ElevatedButton("Click me!", on_click=lambda _: set_count(count + 1)),
])
def main(page: ft.Page):
page.add(ClickExample())
ft.run(main)Lưu ý: Dùng lambda _: (với underscore) khi không cần event object.
📝 Event Object (e)
Khi cần thông tin từ event:
def handle_click(e):
print(e.control) # Control phát sinh event
print(e.control.data) # Data attribute của controlTruyền dữ liệu qua data
@ft.component
def ItemList():
selected, set_selected = ft.use_state("")
def handle_click(e):
set_selected(e.control.data)
return ft.Column([
ft.Text(f"Selected: {selected}"),
ft.ElevatedButton("Item 1", data="item-1", on_click=handle_click),
ft.ElevatedButton("Item 2", data="item-2", on_click=handle_click),
ft.ElevatedButton("Item 3", data="item-3", on_click=handle_click),
])✏️ on_change - Xử lý thay đổi giá trị
Dùng với TextField, Checkbox, Dropdown… trong Declarative style:
@ft.component
def LiveSearch():
query, set_query = ft.use_state("")
return ft.Column([
ft.TextField(
label="Tìm kiếm",
value=query,
on_change=lambda e: set_query(e.control.value),
),
ft.Text(f"Bạn đang tìm: {query}") if query else ft.Container(),
])Kết quả:
⌨️ on_submit - Khi nhấn Enter
@ft.component
def SubmitExample():
items, set_items = ft.use_state([])
input_val, set_input = ft.use_state("")
def handle_submit(_):
if input_val:
set_items([*items, input_val])
set_input("")
return ft.Column([
ft.TextField(
label="Nhập và nhấn Enter",
value=input_val,
on_change=lambda e: set_input(e.control.value),
on_submit=handle_submit,
),
ft.Column([ft.Text(f"• {item}") for item in items]),
])🎯 on_focus / on_blur
@ft.component
def FocusExample():
focused, set_focused = ft.use_state(False)
return ft.Container(
content=ft.TextField(
label="Focus me",
on_focus=lambda _: set_focused(True),
on_blur=lambda _: set_focused(False),
),
border=ft.border.all(2, ft.Colors.GREEN if focused else ft.Colors.GREY),
padding=10,
border_radius=10,
)🖱️ Hover Events
@ft.component
def HoverCard():
hovered, set_hovered = ft.use_state(False)
return ft.Container(
content=ft.Text("Hover me!"),
bgcolor=ft.Colors.GREEN_200 if hovered else ft.Colors.BLUE_100,
padding=20,
border_radius=10,
on_hover=lambda e: set_hovered(e.data == "true"),
)🎯 Ví dụ: Login Form (Declarative)
import flet as ft
@ft.component
def LoginForm():
username, set_username = ft.use_state("")
password, set_password = ft.use_state("")
message, set_message = ft.use_state("")
msg_color, set_color = ft.use_state(ft.Colors.BLACK)
def login_clicked(_):
if not username:
set_message("Vui lòng nhập username")
set_color(ft.Colors.RED)
elif not password:
set_message("Vui lòng nhập password")
set_color(ft.Colors.RED)
else:
set_message(f"Xin chào, {username}!")
set_color(ft.Colors.GREEN)
def clear_clicked(_):
set_username("")
set_password("")
set_message("")
return ft.Card(
content=ft.Container(
content=ft.Column([
ft.Text("Đăng nhập", size=24, weight=ft.FontWeight.BOLD),
ft.TextField(
label="Username",
width=300,
value=username,
on_change=lambda e: set_username(e.control.value),
),
ft.TextField(
label="Password",
password=True,
width=300,
value=password,
on_change=lambda e: set_password(e.control.value),
),
ft.Text(message, color=msg_color) if message else ft.Container(),
ft.Row([
ft.FilledButton("Đăng nhập", on_click=login_clicked),
ft.OutlinedButton("Xóa", on_click=clear_clicked),
]),
], horizontal_alignment=ft.CrossAxisAlignment.CENTER, spacing=15),
padding=30,
),
width=350,
)
def main(page: ft.Page):
page.title = "Login Form"
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.add(LoginForm())
ft.run(main)Kết quả:
📋 Bảng tổng hợp Events
| Event | Sử dụng với | Mô tả |
|---|---|---|
on_click | Button, Container, Card… | Khi click |
on_change | TextField, Checkbox, Dropdown… | Khi giá trị thay đổi |
on_submit | TextField | Khi nhấn Enter |
on_focus | TextField | Khi focus vào |
on_blur | TextField | Khi mất focus |
on_hover | Container, Card… | Khi hover chuột |
💡 So sánh Imperative vs Declarative
| Imperative (cũ) | Declarative (mới) |
|---|---|
Thay đổi control.value | Gọi set_state(value) |
Phải gọi page.update() | UI tự động cập nhật |
| State lưu trong controls | State lưu trong hooks |
⏭️ Bước tiếp theo
Đã biết xử lý events! Tiếp tục với Components & Observables để học sâu hơn về Declarative UI.
Last updated on