Bài 2: Widget Cơ Bản
Giai đoạn 1 – Nhập Môn · Mục tiêu: Thành thạo các widget cơ bản — Label, Button, Entry, Text, Frame — và biết cách cấu hình từng loại.
1. Widget là gì?
Widget là các thành phần giao diện (controls) trong Tkinter: nút bấm, ô nhập liệu, nhãn văn bản, v.v.
| Widget | Mô tả | Dùng khi nào |
|---|---|---|
Label | Hiển thị văn bản / hình ảnh | Tiêu đề, nhãn, thông báo |
Button | Nút bấm kích hoạt hành động | Click để thực hiện lệnh |
Entry | Ô nhập 1 dòng văn bản | Tên, email, mật khẩu |
Text | Vùng nhập nhiều dòng | Ghi chú, nội dung dài |
Frame | Khung chứa widget khác | Nhóm các widget lại |
2. Label — Nhãn văn bản
2.1. Label cơ bản
import tkinter as tk
root = tk.Tk()
root.title("Label Demo")
root.geometry("400x300")
# Label đơn giản
lbl = tk.Label(root, text="Xin chào!")
lbl.pack()
root.mainloop()
2.2. Tùy chỉnh Label
import tkinter as tk
root = tk.Tk()
root.geometry("400x350")
# Label với nhiều tùy chỉnh
lbl = tk.Label(
root,
text="Tiêu đề chính",
font=("Arial", 20, "bold"),
fg="#2C3E50", # Màu chữ
bg="#ECF0F1", # Màu nền
width=20, # Chiều rộng (tính theo ký tự)
height=2, # Chiều cao (tính theo dòng)
relief="groove", # Kiểu viền: flat, raised, sunken, groove, ridge
padx=10, # Padding ngang bên trong
pady=10, # Padding dọc bên trong
anchor="center" # Căn chỉnh: n, s, e, w, center, nw, ne, sw, se
)
lbl.pack(pady=20)
root.mainloop()
2.3. Cập nhật Label động
import tkinter as tk
root = tk.Tk()
root.geometry("300x200")
count = 0
lbl = tk.Label(root, text="0", font=("Arial", 30))
lbl.pack(pady=20)
def tang():
global count
count += 1
lbl.config(text=str(count)) # Cập nhật nội dung
tk.Button(root, text="Tăng", command=tang).pack()
root.mainloop()
:::tip StringVar — Cách khuyến nghị
Thay vì dùng label.config(text=...), nên dùng StringVar để liên kết dữ liệu với widget:
var = tk.StringVar(value="0")
label = tk.Label(root, textvariable=var)
var.set("Giá trị mới") # Label tự động cập nhật
:::
3. Button — Nút bấm
3.1. Button cơ bản
import tkinter as tk
root = tk.Tk()
root.geometry("300x200")
def say_hello():
print("Xin chào! ")
# Cách 1: command truyền tên hàm
btn1 = tk.Button(root, text="In ra console", command=say_hello)
btn1.pack(pady=10)
# Cách 2: lambda cho lệnh ngắn
btn2 = tk.Button(root, text="Thoát", command=lambda: root.destroy())
btn2.pack(pady=10)
root.mainloop()
3.2. Bật/tắt Button
import tkinter as tk
root = tk.Tk()
root.geometry("300x200")
def toggle():
if btn_action["state"] == "normal":
btn_action.config(state="disabled")
btn_toggle.config(text="Bật lại")
else:
btn_action.config(state="normal")
btn_toggle.config(text="Tắt đi")
btn_action = tk.Button(root, text="Hành động", command=lambda: print("Click!"))
btn_action.pack(pady=10)
btn_toggle = tk.Button(root, text="Tắt đi", command=toggle)
btn_toggle.pack(pady=10)
root.mainloop()
3.3. Button style đẹp
import tkinter as tk
root = tk.Tk()
root.geometry("350x250")
root.configure(bg="#1A1A2E")
styles = {
"primary": {"bg": "#3498DB", "activebackground": "#2980B9"},
"success": {"bg": "#27AE60", "activebackground": "#229954"},
"danger": {"bg": "#E74C3C", "activebackground": "#CB4335"},
}
for name, style in styles.items():
btn = tk.Button(
root,
text=name.capitalize(),
font=("Arial", 11, "bold"),
fg="white",
activeforeground="white",
relief="flat",
padx=20, pady=8,
cursor="hand2",
**style
)
btn.pack(pady=8)
root.mainloop()
4. Entry — Ô nhập liệu 1 dòng
4.1. Entry cơ bản
import tkinter as tk
root = tk.Tk()
root.geometry("350x200")
tk.Label(root, text="Nhập tên:").pack(pady=5)
entry = tk.Entry(root, width=30, font=("Arial", 12))
entry.pack(pady=5)
def show_name():
name = entry.get() # Lấy nội dung
print(f"Tên: {name}")
tk.Button(root, text="Xác nhận", command=show_name).pack(pady=10)
root.mainloop()
4.2. Ô mật khẩu
import tkinter as tk
root = tk.Tk()
root.geometry("350x200")
tk.Label(root, text="Mật khẩu:").pack(pady=5)
# show="*" ẩn ký tự nhập
entry_pass = tk.Entry(root, show="*", width=25, font=("Arial", 12))
entry_pass.pack(pady=5)
def show_pass():
print(entry_pass.get())
tk.Button(root, text="Xem mật khẩu", command=show_pass).pack(pady=10)
root.mainloop()
4.3. Các thao tác với Entry
import tkinter as tk
root = tk.Tk()
root.geometry("350x250")
entry = tk.Entry(root, width=30)
entry.pack(pady=10)
# Đặt nội dung ban đầu
entry.insert(0, "Nội dung mặc định")
def clear():
entry.delete(0, tk.END) # Xóa toàn bộ
def get_selection():
try:
print(entry.selection_get()) # Lấy văn bản đang chọn
except:
print("Không có gì được chọn")
tk.Button(root, text="Xóa", command=clear).pack(pady=5)
tk.Button(root, text="Lấy vùng chọn", command=get_selection).pack(pady=5)
root.mainloop()
5. Text — Vùng nhập nhiều dòng
5.1. Text cơ bản
import tkinter as tk
root = tk.Tk()
root.geometry("400x350")
tk.Label(root, text="Ghi chú:", font=("Arial", 11)).pack(anchor="w", padx=10)
text_area = tk.Text(
root,
width=45,
height=10,
font=("Arial", 11),
wrap="word", # Xuống dòng theo từ (word/char/none)
padx=5, pady=5
)
text_area.pack(padx=10, pady=5)
def get_text():
content = text_area.get("1.0", tk.END) # "dòng.cột"
print(repr(content))
tk.Button(root, text="Lấy nội dung", command=get_text).pack(pady=5)
root.mainloop()
5.2. Thêm Scrollbar cho Text
import tkinter as tk
root = tk.Tk()
root.geometry("400x350")
frame = tk.Frame(root)
frame.pack(fill="both", expand=True, padx=10, pady=10)
scrollbar = tk.Scrollbar(frame)
scrollbar.pack(side="right", fill="y")
text_area = tk.Text(
frame,
yscrollcommand=scrollbar.set,
font=("Consolas", 11)
)
text_area.pack(side="left", fill="both", expand=True)
scrollbar.config(command=text_area.yview)
# Thêm nhiều dòng để test scroll
for i in range(50):
text_area.insert(tk.END, f"Dòng {i+1}: Hello Tkinter!\n")
root.mainloop()
5.3. Thao tác với Text
import tkinter as tk
root = tk.Tk()
root.geometry("400x300")
text = tk.Text(root, font=("Arial", 11))
text.pack(fill="both", expand=True, padx=10, pady=10)
def insert_text():
text.insert(tk.END, "Nội dung thêm vào\n") # Chèn cuối
text.insert("1.0", ">> Đầu trang\n") # Chèn đầu
text.insert("2.5", "<<giữa>>") # Chèn tại dòng 2, cột 5
def clear_text():
text.delete("1.0", tk.END) # Xóa toàn bộ
def get_all():
print(text.get("1.0", tk.END))
frame = tk.Frame(root)
frame.pack()
tk.Button(frame, text="Thêm", command=insert_text).pack(side="left", padx=5)
tk.Button(frame, text="Xóa", command=clear_text).pack(side="left", padx=5)
tk.Button(frame, text="Lấy", command=get_all).pack(side="left", padx=5)
root.mainloop()
6. Frame — Khung chứa
Frame là widget vô hình dùng để nhóm và tổ chức các widget khác.
import tkinter as tk
root = tk.Tk()
root.title("Frame Demo")
root.geometry("400x300")
# Frame tiêu đề
header = tk.Frame(root, bg="#2C3E50", height=60)
header.pack(fill="x")
header.pack_propagate(False) # Giữ nguyên kích thước
tk.Label(header, text=" Ứng dụng của tôi",
font=("Arial", 14, "bold"),
fg="white", bg="#2C3E50").pack(side="left", padx=15, pady=15)
# Frame nội dung
content = tk.Frame(root, bg="#ECF0F1")
content.pack(fill="both", expand=True, padx=10, pady=10)
tk.Label(content, text="Nội dung chính ở đây",
bg="#ECF0F1", font=("Arial", 12)).pack(expand=True)
# Frame chân trang
footer = tk.Frame(root, bg="#BDC3C7", height=35)
footer.pack(fill="x", side="bottom")
footer.pack_propagate(False)
tk.Label(footer, text=" 2025 My App",
bg="#BDC3C7", fg="#7F8C8D").pack(pady=7)
root.mainloop()
7. Biến kiểm soát (Control Variables)
Tkinter có các biến đặc biệt để liên kết dữ liệu với widget:
| Biến | Kiểu dữ liệu | Dùng với |
|---|---|---|
StringVar | str | Label, Entry, Combobox |
IntVar | int | Checkbutton, Radiobutton, Spinbox |
DoubleVar | float | Scale, Entry |
BooleanVar | bool | Checkbutton |
import tkinter as tk
root = tk.Tk()
root.geometry("350x200")
# StringVar liên kết Entry và Label
var = tk.StringVar(value="Gõ gì đó...")
entry = tk.Entry(root, textvariable=var, width=30)
entry.pack(pady=10)
# Label tự động cập nhật khi Entry thay đổi
label = tk.Label(root, textvariable=var, font=("Arial", 14), fg="#2980B9")
label.pack(pady=10)
root.mainloop()
Bài tập thực hành
Trắc nghiệm
-
Hàm nào lấy nội dung của Entry?
- A.
entry.value() - B.
entry.read() - C.
entry.get() - D.
entry.text()
- A.
-
Tham số nào ẩn ký tự trong Entry (dùng cho mật khẩu)?
- A.
hidden=True - B.
mask="*" - C.
show="*" - D.
password=True
- A.
-
Để xóa toàn bộ nội dung Text widget, dùng lệnh nào?
- A.
text.clear() - B.
text.delete("1.0", tk.END) - C.
text.remove(all=True) - D.
text.erase()
- A.
Thực hành
- Tạo form "Đăng ký thành viên" gồm: Họ tên (Entry), Email (Entry), Mật khẩu (Entry ẩn), nút "Đăng ký" in thông tin ra console.
- Tạo app "Notepad mini": Text với Scrollbar, 3 nút: Xóa, Đếm từ, Đảo ngược văn bản.
- Dùng
StringVartạo form có Label tự động hiển thị nội dung đang gõ trong Entry. - (Nâng cao) Tạo app "Bộ chuyển đổi nhiệt độ" (Celsius Fahrenheit) dùng Entry + Label + Button.
Bài trước: Bài 1 – Giới Thiệu Tkinter · Bài tiếp: Bài 3 – Quản Lý Bố Cục