Tạo ứng dụng Python đồ họa đầu tiên của bạn: Bắt đầu với Tkinter

Tạo ra các dự án lập trình là điều tuyệt vời. Nhưng nếu nó có giao diện đồ họa thì sao? Tuyệt vời hơn nữa! Xây dựng một ứng dụng GUI (Giao diện người dùng đồ họa) có nhiều lợi ích. Bạn sẽ có được một sản phẩm mà ngay cả những người bạn không am hiểu về công nghệ cũng có thể đánh giá cao. Đó là lý do tại sao chúng ta sẽ tạo một ứng dụng GUI bằng Python và học thư viện Tkinter trong quá trình này.
Xem thêm: Hướng dẫn cách tích hợp ứng dụng ChatGPT một cách liền mạch với Google Drive
1. Chúng ta sẽ tạo gì?
Đối với hướng dẫn này, tôi quyết định tạo một ứng dụng danh sách việc cần làm (to-do list app). Đây là một dự án kinh điển, không quá khó và đồng thời dạy được rất nhiều khái niệm lập trình. Hơn nữa, nếu bạn thích sản phẩm cuối cùng, bạn có thể sử dụng nó cho chính mình.
Có một phiên bản console của ứng dụng danh sách việc cần làm bằng Python. Nó bao gồm nhiều kiến thức cơ bản mà bạn nên biết. Vì vậy, tôi khuyên bạn nên xem qua nó trước vì nó sẽ giúp bạn hiểu hướng dẫn này tốt hơn. Tuy nhiên, điều đó không hoàn toàn bắt buộc vì tôi sẽ hướng dẫn bạn qua mã và giải thích những gì đang diễn ra, để bạn nắm được mà không cần nhiều kiến thức trước đó.
Tôi cũng khuyên bạn nên ôn lại kiến thức cơ bản về Python phòng trường hợp bạn chưa biết ngôn ngữ này. Nếu không, sẽ khó khăn để bạn theo dõi hướng dẫn này.
2. Thiết lập Tkinter
Điều tốt về Tkinter là nó được đi kèm với bản cài đặt Python của bạn. Vì vậy, không cần phải cài đặt bất cứ thứ gì. Hãy xác minh điều này bằng cách nhập mô-đun tkinter
và kiểm tra phiên bản của nó.
import tkinter as tk
print(tk.TkVersion)
Bạn sẽ nhận được số phiên bản trên console của mình. Đối với tôi, nó là 8.6. Nếu bạn gặp lỗi, điều đó có nghĩa là bản cài đặt Python của bạn có thể không có nó. Bạn có thể cần cài đặt lại Python, hoặc trên Linux, cài đặt gói chính xác cho tkinter
theo bản phân phối của bạn.
3. Tạo cửa sổ chính
Nếu mã hoạt động với bạn, thì bây giờ chúng ta hãy tạo cửa sổ chính. Chúng ta sẽ thiết lập cửa sổ với kích thước và tiêu đề thích hợp.
import tkinter as tk
# Tạo cửa sổ ứng dụng chính
root = tk.Tk()
root.title("To-Do List App")
root.geometry("400x500")
# Ngăn không cho cửa sổ thay đổi kích thước
root.resizable(False, False)
# Bắt đầu vòng lặp sự kiện
root.mainloop()
Chúng ta đã làm gì?
- Chúng ta nhập Tkinter và đặt biệt danh là
tk
cho tiện lợi. root = tk.Tk()
tạo cửa sổ ứng dụng chính.- Chúng ta đặt tiêu đề cửa sổ bằng cách sử dụng
root.title()
. root.geometry("400x500")
đặt kích thước cửa sổ.root.resizable(False, False)
ngăn người dùng thay đổi kích thước cửa sổ. Tham số đầu tiên kiểm soát thay đổi kích thước chiều ngang, tham số thứ hai kiểm soát chiều dọc.- Cuối cùng,
root.mainloop()
bắt đầu vòng lặp sự kiện. Điều này rất quan trọng! Nếu không có nó, cửa sổ của bạn sẽ xuất hiện và ngay lập tức đóng lại.
Khi bạn chạy mã này, bạn sẽ thấy một cửa sổ trống có tiêu đề “To-Do List App.” Hiện tại nó trống, nhưng trong bước tiếp theo, chúng ta sẽ bắt đầu điền các widget vào đó.
4. Thêm các Widget cần thiết
Một ứng dụng danh sách việc cần làm cần nhiều widget: một trường nhập liệu, các nút để quản lý tác vụ và một trường để xem chúng. Hãy bắt đầu thêm chúng. Viết các dòng này sau dòng root.resizable(False, False)
.
task_entry = tk.Entry(root, width=35, font=("Arial", 12))
task_entry.pack(pady=10)
Chúng ta tạo một widget Entry
cho đầu vào văn bản một dòng. Chúng ta đặt chiều rộng, phông chữ và một số đệm dọc cho nó. Sau đó chúng ta thêm một nút.
add_button = tk.Button(root, text="Add Task", width=20, font=("Arial", 10))
add_button.pack(pady=5)
Một lần nữa, chúng ta đặt chiều rộng, phông chữ, một số đệm dọc và một nhãn văn bản cho nó. Nút này sẽ hoạt động như nút thêm tác vụ. Sau đó, chúng ta tạo một listbox để hiển thị các tác vụ.
task_listbox = tk.Listbox(root, width=50, height=15, font=("Arial", 10))
task_listbox.pack(pady=10)
Giống như các widget trước, chúng ta cung cấp cho nó một số thuộc tính, bao gồm cả chiều cao của nó. Chúng ta sử dụng trình quản lý hình học pack()
để định vị các widget theo thứ tự chúng được thêm vào. Tkinter cũng cung cấp grid()
để kiểm soát chính xác hơn. Đối với hướng dẫn này, chúng ta sẽ giữ lại pack()
vì nó đơn giản hơn cho người mới bắt đầu.
Khi bạn chạy mã này, bạn sẽ thấy một trường văn bản trống ở trên cùng, một nút “Add Task” bên dưới nó, và một listbox trống lớn ở dưới cùng.
Bây giờ nó trông giống một ứng dụng việc cần làm hơn.
5. Xử lý sự kiện (Handling Events)
Hiện tại, ứng dụng của chúng ta chỉ có giao diện người dùng (UI). Chưa có chức năng nào cả. Hãy làm cho ứng dụng của chúng ta có tính tương tác. Chúng ta sẽ tạo một hàm để thêm tác vụ vào listbox. Thêm đoạn mã này sau dòng root.resizable(False, False)
.
def add_task():
task = task_entry.get()
if task:
task_listbox.insert(tk.END, task)
task_entry.delete(0, tk.END)
else:
print("Please enter a task!")
Đầu tiên, chúng ta lấy văn bản trong trường nhập liệu. Sau đó, chúng ta kiểm tra xem trường có trống hay không bằng một điều kiện. Nếu không trống, chúng ta chèn văn bản, tức là tác vụ, vào listbox và xóa trường nhập liệu. Ngược lại, chúng ta in một thông báo đơn giản ra console rằng không có tác vụ nào được nhập. Việc tiếp theo là kết nối hàm này với nút.
add_button = tk.Button(root, text="Add Task", width=20, font=("Arial", 10), command=add_task)
Chúng ta truyền một đối số mới, đó là hàm add_task()
. Điều này báo cho nút biết rằng nó phải gọi hàm khi được nhấp. Lưu ý rằng chúng ta không đặt dấu ngoặc đơn khi truyền đối số.
Hãy thử điều này. Viết một cái gì đó vào trường nhập và nhấp vào nút “Add Task” để xem tác vụ có được thêm vào hay không. Sau đó thử thêm một tác vụ khi trường nhập trống.
Tuyệt vời. Nó hoạt động như mong đợi. Bây giờ bạn đã có thể thêm các tác vụ.
6. Làm việc với giao diện người dùng (UI)
Hãy thêm nhiều chức năng hơn để làm cho ứng dụng Danh sách Việc cần làm của chúng ta thực sự hữu ích. Chúng ta sẽ thêm khả năng xóa tác vụ, xóa tất cả tác vụ, và đánh dấu tác vụ là hoàn thành. Hãy thêm một hàm để xóa tác vụ. Thêm đoạn mã này sau hàm add_task()
.
def delete_task():
try:
selected_index = task_listbox.curselection()[0]
task_listbox.delete(selected_index)
except IndexError:
print("Vui lòng chọn một tác vụ để xóa!")
Ở đây, curselection()[0]
lấy mục được chọn đầu tiên (và duy nhất) từ một tuple chứa các chỉ mục của mục được chọn. Sau đó, chúng ta xóa mục ở chỉ mục đó. Chúng ta cũng sử dụng try/except
để xử lý lỗi tốt hơn. Sau đó, hãy thêm một hàm để xóa tất cả các tác vụ trong listbox.
def clear_all_tasks():
task_listbox.delete(0, tk.END)
Hàm này xóa tất cả các tác vụ từ đầu đến cuối. Bây giờ, hãy thêm một hàm sẽ đánh dấu một tác vụ là hoàn thành.
def mark_complete():
try:
selected_index = task_listbox.curselection()[0]
task = task_listbox.get(selected_index)
# Kiểm tra xem tác vụ đã được đánh dấu hoàn thành chưa
if not task.startswith("✓ "):
# Đánh dấu là hoàn thành với dấu kiểm
task_listbox.delete(selected_index)
task_listbox.insert(selected_index, "✓ " + task)
task_listbox.itemconfig(selected_index, fg="gray")
except IndexError:
print("Vui lòng chọn một tác vụ để đánh dấu là hoàn thành!")
Có rất nhiều điều đang diễn ra ở đây. Đầu tiên, chúng ta đang truy xuất tác vụ đã chọn, giống như chúng ta đã làm trước đó cho việc xóa. Sau đó, chúng ta sử dụng các điều kiện để kiểm tra xem văn bản của tác vụ có đáp ứng một yêu cầu cụ thể hay không. Đó là, nếu nó bắt đầu bằng dấu kiểm ✓
theo sau là một khoảng trắng.
Nếu không, thì nó chưa hoàn thành. Chúng ta xóa tác vụ khỏi listbox và chèn lại nó ở cùng vị trí với dấu tick và một khoảng trắng. Để làm cho trực quan rõ ràng, chúng ta cũng làm cho màu tiền cảnh (fg
) của nó chuyển sang màu xám. Nếu không có tác vụ nào được chọn, chúng ta in một thông báo hữu ích. Vì không có tùy chọn chỉnh sửa trực tiếp, chúng ta xóa tác vụ trước và chèn lại nó ở cùng vị trí với dấu đánh dấu.
Chúng ta vẫn cần liên kết các chức năng này với một số nút. Đầu tiên, hãy tạo một frame nơi chúng ta sẽ đặt các nút mới. Thêm đoạn này ngay trước root.mainloop()
.
button_frame = tk.Frame(root)
button_frame.pack(pady=10)
Frame
là một widget container nhóm các widget khác lại với nhau. Bên trong frame này, chúng ta đặt ba nút mới: một nút xóa, một nút xóa tất cả và một nút đánh dấu là hoàn thành.
mark_button = tk.Button(button_frame, text="Mark Complete", width=15,
font=("Arial", 10), command=mark_complete)
mark_button.grid(row=0, column=0, padx=5)
delete_button = tk.Button(button_frame, text="Delete Task", width=15,
font=("Arial", 10), command=delete_task)
delete_button.grid(row=0, column=1, padx=5)
clear_button = tk.Button(button_frame, text="Clear All", width=15,
font=("Arial", 10), command=clear_all_tasks)
clear_button.grid(row=0, column=2, padx=5)
Không giống như trước, chúng ta đã sử dụng grid()
ở đây. Nó cung cấp cho chúng ta sự căn chỉnh nút ngang chính xác. Các tham số row
(hàng) và column
(cột) xác định nơi chúng ta muốn đặt widget cụ thể bên trong bố cục lưới. Chúng ta cũng thêm một số đệm ngang (padx
) cho mỗi nút và chức năng tương ứng của nó.
Bây giờ ứng dụng của chúng ta đang hoạt động như một ứng dụng việc cần làm thực sự.
7. Một vài điều chỉnh cuối cùng
Ứng dụng hoạt động tốt. Nhưng nó hơi buồn tẻ. Hãy làm cho nó đẹp hơn để trông chuyên nghiệp hơn. Thêm dòng này sau dòng root.resizable(False, False)
.
root.config(bg="#f0f0f0") # Nền màu xám nhạt
Nó đặt một nền màu xám nhạt dễ chịu cho toàn bộ cửa sổ. Tiếp theo, hãy tạo một phần tiêu đề (header). Thêm đoạn mã này sau hàm mark_complete()
(hoặc sau tất cả các hàm logic).
header_frame = tk.Frame(root, bg="#4a7c9e")
header_frame.pack(fill=tk.X)
header_label = tk.Label(header_frame, text="📝 My To-Do List",
font=("Arial", 18, "bold"),
bg="#4a7c9e", fg="white")
header_label.pack(pady=15)
Với fill=tk.X
, chúng ta làm cho frame trải dài theo chiều ngang qua cửa sổ. Chúng ta đã thêm một widget Label
với một số thuộc tính. Tiếp theo, hãy làm việc trên phần nhập liệu (input).
input_frame = tk.Frame(root, bg="#f0f0f0")
input_frame.pack(pady=20)
task_entry = tk.Entry(input_frame, width=35, font=("Arial", 13),
bd=2, relief=tk.GROOVE)
task_entry.pack(side=tk.LEFT, padx=10, ipady=5)
task_entry.bind('<Return>', lambda event: add_task())
add_button = tk.Button(input_frame, text="Add Task", width=12,
font=("Arial", 11, "bold"),
bg="#5cb85c", fg="white",
activebackground="#4cae4c",
bd=0, cursor="hand2",
command=add_task)
add_button.pack(side=tk.LEFT)
Chúng ta đã thêm một đường viền vào trường nhập liệu và tạo cho nó hiệu ứng GROOVE
. Chúng ta cũng đã thêm một số kiểu dáng cho nút. Tiếp theo, là phần listbox.
list_frame = tk.Frame(root, bg="#f0f0f0")
list_frame.pack(pady=10, padx=20)
scrollbar = tk.Scrollbar(list_frame, orient=tk.VERTICAL)
task_listbox = tk.Listbox(list_frame, width=55, height=14,
font=("Arial", 11),
bd=2, relief=tk.SUNKEN,
selectmode=tk.SINGLE,
activestyle='none',
bg="white",
selectbackground="#d4e6f1",
selectforeground="black",
yscrollcommand=scrollbar.set)
scrollbar.config(command=task_listbox.yview)
task_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
Trong frame của listbox, chúng ta có một widget Scrollbar
mới. Nếu listbox trở nên lớn, nó sẽ cuộn theo chiều dọc. Chúng ta cũng đã thêm một số thuộc tính vào widget Listbox
, thiết lập màu sắc, kiểu đường viền và hành vi cuộn của nó. Bây giờ hãy làm việc trên các nút còn lại.
button_frame = tk.Frame(root, bg="#f0f0f0")
button_frame.pack(pady=20)
mark_button = tk.Button(button_frame, text="✓ Mark Complete", width=15,
font=("Arial", 10, "bold"),
bg="#5bc0de", fg="white",
activebackground="#46b8da",
bd=0, cursor="hand2",
command=mark_complete)
mark_button.grid(row=0, column=0, padx=8)
delete_button = tk.Button(button_frame, text="✕ Delete Task", width=15,
font=("Arial", 10, "bold"),
bg="#d9534f", fg="white",
activebackground="#c9302c",
bd=0, cursor="hand2",
command=delete_task)
delete_button.grid(row=0, column=1, padx=8)
clear_button = tk.Button(button_frame, text="Clear All", width=15,
font=("Arial", 10, "bold"),
bg="#f0ad4e", fg="white",
activebackground="#ec971f",
bd=0, cursor="hand2",
command=clear_all_tasks)
clear_button.grid(row=0, column=2, padx=8)
Chúng ta đang sử dụng màu sắc và các kiểu dáng khác phù hợp với hành động của mỗi nút để làm cho chúng nổi bật về mặt hình ảnh. Cuối cùng, hãy thêm một phần chân trang (footer).
footer_label = tk.Label(root, text="Chọn một tác vụ và sử dụng các nút để quản lý nó",
font=("Arial", 9, "italic"),
bg="#f0f0f0", fg="#666666")
footer_label.pack(side=tk.BOTTOM, pady=10)
Chúng ta đã sử dụng widget Label
ở đây làm phần văn bản. Khi bạn chạy phiên bản hiện tại, bạn sẽ được thấy một ứng dụng việc cần làm trông đẹp mắt.
Giao diện trông bóng bẩy và chuyên nghiệp hơn rất nhiều bây giờ. Toàn bộ mã có sẵn trên kho lưu trữ GitHub của tôi để bạn tiện tham khảo, vì vậy hãy thoải mái kiểm tra nó.
Có nhiều điều bạn có thể thêm vào ứng dụng hiện có, chẳng hạn như thao tác tệp, hộp thoại thông báo và tích hợp cơ sở dữ liệu, cùng nhiều thứ khác. Nếu bạn quan tâm đến nhiều dự án Tkinter hơn, bạn cũng có thể xây dựng một công cụ theo dõi chi tiêu. Ngoài ra, hãy kiểm tra tài liệu Tkinter để học thêm.
8. Kết luận
Tạo ứng dụng Python đồ họa đầu tiên với Tkinter là một bước khởi đầu thú vị, mở ra cánh cửa để bạn xây dựng các giao diện người dùng trực quan và thân thiện. Với các bước hướng dẫn chi tiết, bạn có thể dễ dàng làm chủ Tkinter, từ việc tạo cửa sổ cơ bản đến thiết kế các ứng dụng tương tác đầy sáng tạo. Hy vọng bài viết này đã truyền cảm hứng để bạn bắt đầu hành trình lập trình giao diện với Python, sẵn sàng biến ý tưởng của mình thành hiện thực với những ứng dụng đồ họa độc đáo!
Xem thêm: Hướng dẫn cách tích hợp ứng dụng ChatGPT một cách liền mạch với Google Drive
Nếu bạn cần laptop hoặc PC cấu hình mạnh để lập trình Python và phát triển ứng dụng Tkinter mượt mà, hãy ghé qua COHOTECH – địa chỉ uy tín cung cấp thiết bị công nghệ và dịch vụ hỗ trợ kỹ thuật chuyên nghiệp. Đội ngũ COHOTECH cam kết mang đến giải pháp tối ưu và những ưu đãi hấp dẫn để bạn chinh phục mọi thử thách lập trình. Theo dõi chúng tôi để khám phá thêm nhiều mẹo công nghệ hữu ích và sản phẩm độc quyền!
Bạn đã thử tạo ứng dụng đầu tiên với Tkinter chưa? Hãy chia sẻ kinh nghiệm hoặc đặt câu hỏi trong phần bình luận bên dưới nhé! Nếu bài viết này hữu ích, đừng quên like,