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à.