Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Cách sử dụng phương thức after() của Tkinter
Trong giao diện người dùng (GUI) với Tkinter, việc quản lý thời gian và lên lịch thực hiện các hành động là rất quan trọng để đảm bảo ứng dụng hoạt động mượt mà và phản hồi nhanh chóng. Trong bài viết này, bạn sẽ được tìm hiểu về phương thức after() của Tkinter, một công cụ mạnh mẽ giúp bạn dễ dàng lên lịch thực hiện các hành động sau khi một khoảng thời gian chờ (timeout) đã trôi qua. Bằng cách sử dụng phương thức này, bạn có thể kiểm soát tốt hơn các tác vụ trong ứng dụng, giúp tối ưu hóa trải nghiệm người dùng mà không làm gián đoạn giao diện chính.

Giới thiệu về phương thức Tkinter after()
Tất cả các widget của Tkinter đều có phương thức after() với cú pháp sau:
widget.after(delay, callback=None)
Phương thức after() sẽ gọi hàm callback một lần sau khi một khoảng thời gian delay (tính bằng mili giây) đã trôi qua trong vòng lặp chính của Tkinter.
Nếu bạn không cung cấp hàm callback, phương thức after() sẽ hoạt động giống như hàm time.sleep(). Tuy nhiên, after() sử dụng đơn vị mili giây thay vì giây.
Bài viết này được đăng tại [free tuts .net]
Ví dụ về phương thức Tkinter after()
Hãy xem xét chương trình sau:
import tkinter as tk
from tkinter import ttk
import time
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Tkinter after() Demo')
self.geometry('300x100')
self.style = ttk.Style(self)
self.button = ttk.Button(self, text='Wait 3 seconds')
self.button['command'] = self.start
self.button.pack(expand=True, ipadx=10, ipady=5)
def start(self):
self.change_button_color('red')
time.sleep(3)
self.change_button_color('black')
def change_button_color(self, color):
self.style.configure('TButton', foreground=color)
if __name__ == "__main__":
app = App()
app.mainloop()
Chương trình này có một nút bấm. Khi bạn nhấn nút, màu của nút sẽ chuyển sang đỏ, chương trình sẽ chờ 3 giây, sau đó màu của nút chuyển lại thành đen.
Tuy nhiên, khi bạn chạy chương trình và nhấn nút, bạn sẽ nhận thấy rằng màu của nút không thay đổi và cửa sổ bị đóng băng trong 3 giây.

Nguyên nhân là do hàm sleep() đã làm gián đoạn quá trình thực thi của luồng chính (main thread), do đó Tkinter không thể cập nhật giao diện người dùng (GUI).
Để khắc phục, bạn có thể sử dụng phương thức after() để lên lịch cho hành động thay đổi màu sắc của nút thay vì làm gián đoạn luồng chính. Ví dụ:
import tkinter as tk
from tkinter import ttk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Tkinter after() Demo')
self.geometry('300x100')
self.style = ttk.Style(self)
self.button = ttk.Button(self, text='Wait 3 seconds')
self.button['command'] = self.start
self.button.pack(expand=True, ipadx=10, ipady=5)
def start(self):
self.change_button_color('red')
self.after(3000, lambda: self.change_button_color('black'))
def change_button_color(self, color):
self.style.configure('TButton', foreground=color)
print(color)
if __name__ == "__main__":
app = App()
app.mainloop()
Kết quả:

Tại sao nên sử dụng phương thức Tkinter after()?
Trong Python, một chương trình có thể có một hoặc nhiều luồng (thread). Khi bạn khởi chạy một ứng dụng Tkinter, nó sẽ chạy trong luồng chính (main thread).
Vòng lặp chính của Tkinter phải được bắt đầu từ luồng chính và chịu trách nhiệm xử lý các sự kiện và cập nhật giao diện người dùng (GUI).
Nếu bạn bắt đầu một tác vụ chạy lâu trong luồng chính, GUI sẽ bị đóng băng và không phản hồi lại các sự kiện của người dùng.
Để tránh tác vụ dài hạn làm gián đoạn luồng chính, bạn có thể lên lịch một hành động không được thực hiện sớm hơn thời gian đã chỉ định bằng cách sử dụng phương thức after().
Tkinter sẽ thực hiện hàm callback trong luồng chính khi luồng chính không bận.
Ví dụ với phương thức Tkinter after()
Chương trình sau hiển thị một đồng hồ số, sử dụng phương thức after() để cập nhật giờ hiện tại mỗi giây:
import tkinter as tk
from tkinter import ttk
import time
class DigitalClock(tk.Tk):
def __init__(self):
super().__init__()
# Cấu hình cửa sổ chính
self.title('Digital Clock')
self.resizable(0, 0)
self.geometry('250x80')
self['bg'] = 'black'
# Thay đổi màu nền thành màu đen
self.style = ttk.Style(self)
self.style.configure(
'TLabel',
background='black',
foreground='red')
# Nhãn hiển thị thời gian
self.label = ttk.Label(
self,
text=self.time_string(),
font=('Digital-7', 40))
self.label.pack(expand=True)
# Lên lịch cập nhật mỗi giây
self.label.after(1000, self.update)
def time_string(self):
return time.strftime('%H:%M:%S')
def update(self):
"""Cập nhật nhãn mỗi giây"""
self.label.configure(text=self.time_string())
# Lên lịch cập nhật khác
self.label.after(1000, self.update)
if __name__ == "__main__":
clock = DigitalClock()
clock.mainloop()
Kết quả:

Kết bài
Tóm lại, phương thức after() của Tkinter là một công cụ hữu ích để lên lịch thực hiện các hành động sau khi thời gian chờ kết thúc, giúp bạn quản lý tốt hơn các tác vụ trong ứng dụng GUI. Tuy nhiên, vì các callback được thực hiện trong luồng chính, nên bạn cần tránh sử dụng after() cho các tác vụ dài hạn để không gây treo hoặc làm chậm ứng dụng. Thay vào đó, hãy sử dụng các phương pháp khác, như threading, để xử lý những tác vụ phức tạp và đảm bảo giao diện người dùng luôn phản hồi mượt mà.

Các kiểu dữ liệu trong C ( int - float - double - char ...)
Thuật toán tìm ước chung lớn nhất trong C/C++
Cấu trúc lệnh switch case trong C++ (có bài tập thực hành)
ComboBox - ListBox trong lập trình C# winforms
Random trong Python: Tạo số random ngẫu nhiên
Lệnh cin và cout trong C++
Cách khai báo biến trong PHP, các loại biến thường gặp
Download và cài đặt Vertrigo Server
Thẻ li trong HTML
Thẻ article trong HTML5
Cấu trúc HTML5: Cách tạo template HTML5 đầu tiên
Cách dùng thẻ img trong HTML và các thuộc tính của img
Thẻ a trong HTML và các thuộc tính của thẻ a thường dùng