Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Các Frame hướng đối tượng trong Tkinter
Trong giao diện người dùng với Tkinter, việc tổ chức mã nguồn theo hướng đối tượng là một cách tiếp cận hiệu quả để xây dựng các ứng dụng linh hoạt và dễ bảo trì. Thay vì tạo và quản lý các widget trong hàm chính, bạn có thể tận dụng sức mạnh của các lớp và đối tượng để xây dựng các khung (Frame) có cấu trúc rõ ràng. Bài viết này sẽ hướng dẫn bạn cách kế thừa từ lớp ttk.Frame
và sử dụng nó trong cửa sổ chính của ứng dụng Tkinter, giúp bạn tổ chức mã nguồn một cách gọn gàng và dễ dàng mở rộng.
Giới thiệu các Frame hướng đối tượng trong Tkinter
Trong bài hướng dẫn trước, bạn đã học cách kế thừa từ lớp Tkinter.Tk
. Tuy nhiên, một ứng dụng Tkinter chỉ nên có một phiên bản Tk duy nhất. Do đó, việc kế thừa từ lớp ttk.Frame
và sử dụng lớp con đó trong cửa sổ chính là điều phổ biến.
Để kế thừa từ lớp ttk.Frame
, bạn sử dụng cú pháp sau:
class MainFrame(ttk.Frame): pass
Vì một Frame cần một container, bạn cần thêm một tham số vào phương thức __init__()
và gọi phương thức __init__()
của lớp ttk.Frame
như sau:
Bài viết này được đăng tại [free tuts .net]
class MainFrame(ttk.Frame): def __init__(self, container): super().__init__(container)
Dưới đây là ví dụ về lớp MainFrame
hoàn chỉnh có chứa một nhãn (label) và một nút bấm (button). Khi bạn nhấn nút, nó sẽ hiển thị một hộp thoại thông báo:
class MainFrame(ttk.Frame): def __init__(self, container): super().__init__(container) options = {'padx': 5, 'pady': 5} # Nhãn self.label = ttk.Label(self, text='Hello, Tkinter!') self.label.pack(**options) # Nút bấm self.button = ttk.Button(self, text='Click Me') self.button['command'] = self.button_clicked self.button.pack(**options) # Hiển thị frame trên container self.pack(**options) def button_clicked(self): showinfo(title='Information', message='Hello, Tkinter!')
Tiếp theo, chúng ta định nghĩa lớp App
kế thừa từ lớp Tk
:
class App(tk.Tk): def __init__(self): super().__init__() # Cấu hình cửa sổ chính self.title('My Awesome App') self.geometry('300x100')
Cuối cùng, bạn có thể khởi chạy ứng dụng thông qua khối lệnh if __name__ == "__main__"
:
if __name__ == "__main__": app = App() frame = MainFrame(app) app.mainloop()
Trong đoạn mã trên:
- Đầu tiên, tạo một phiên bản mới của lớp
App
. - Sau đó, tạo một phiên bản mới của lớp
MainFrame
và đặt container của nó là phiên bản của lớpApp
. - Cuối cùng, khởi động ứng dụng bằng cách gọi
app()
. Điều này sẽ thực thi phương thức__call__()
và kích hoạt vòng lặp chính (mainloop) của cửa sổ chính.
Hoàn chỉnh mã nguồn:
import tkinter as tk from tkinter import ttk from tkinter.messagebox import showinfo class MainFrame(ttk.Frame): def __init__(self, container): super().__init__(container) options = {'padx': 5, 'pady': 5} # Nhãn self.label = ttk.Label(self, text='Hello, Tkinter!') self.label.pack(**options) # Nút bấm self.button = ttk.Button(self, text='Click Me') self.button['command'] = self.button_clicked self.button.pack(**options) # Hiển thị frame trên container self.pack(**options) def button_clicked(self): showinfo(title='Information', message='Hello, Tkinter!') class App(tk.Tk): def __init__(self): super().__init__() # Cấu hình cửa sổ chính self.title('My Awesome App') self.geometry('300x100') if __name__ == "__main__": app = App() frame = MainFrame(app) app.mainloop()
Kết quả:
Ví dụ khung hướng đối tượng khác trong Tkinter
Ví dụ sau sử dụng các lớp để chuyển đổi cửa sổ Replace từ bài hướng dẫn về Frame:
import tkinter as tk from tkinter import ttk class InputFrame(ttk.Frame): def __init__(self, container): super().__init__(container) # Cài đặt trình quản lý bố cục lưới self.columnconfigure(0, weight=1) self.columnconfigure(0, weight=3) self.__create_widgets() def __create_widgets(self): # Nhãn "Find what" ttk.Label(self, text='Find what:').grid(column=0, row=0, sticky=tk.W) keyword = ttk.Entry(self, width=30) keyword.focus() keyword.grid(column=1, row=0, sticky=tk.W) # Nhãn "Replace with" ttk.Label(self, text='Replace with:').grid(column=0, row=1, sticky=tk.W) replacement = ttk.Entry(self, width=30) replacement.grid(column=1, row=1, sticky=tk.W) # Ô chọn "Match Case" match_case = tk.StringVar() match_case_check = ttk.Checkbutton( self, text='Match case', variable=match_case, command=lambda: print(match_case.get())) match_case_check.grid(column=0, row=2, sticky=tk.W) # Ô chọn "Wrap Around" wrap_around = tk.StringVar() wrap_around_check = ttk.Checkbutton( self, variable=wrap_around, text='Wrap around', command=lambda: print(wrap_around.get())) wrap_around_check.grid(column=0, row=3, sticky=tk.W) for widget in self.winfo_children(): widget.grid(padx=0, pady=5) class ButtonFrame(ttk.Frame): def __init__(self, container): super().__init__(container) # Cài đặt trình quản lý bố cục lưới self.columnconfigure(0, weight=1) self.__create_widgets() def __create_widgets(self): ttk.Button(self, text='Find Next').grid(column=0, row=0) ttk.Button(self, text='Replace').grid(column=0, row=1) ttk.Button(self, text='Replace All').grid(column=0, row=2) ttk.Button(self, text='Cancel').grid(column=0, row=3) for widget in self.winfo_children(): widget.grid(padx=0, pady=3) class App(tk.Tk): def __init__(self): super().__init__() self.title('Replace') self.geometry('400x150') self.resizable(0, 0) # Chỉ dành cho Windows (loại bỏ nút thu nhỏ/phóng to) self.attributes('-toolwindow', True) # Bố trí trên cửa sổ chính self.columnconfigure(0, weight=4) self.columnconfigure(1, weight=1) self.__create_widgets() def __create_widgets(self): # Tạo frame nhập liệu input_frame = InputFrame(self) input_frame.grid(column=0, row=0) # Tạo frame các nút bấm button_frame = ButtonFrame(self) button_frame.grid(column=1, row=0) if __name__ == "__main__": app = App() app.mainloop()
Kết quả:
Kết bài
Qua bài viết này, bạn đã học cách kế thừa từ lớp ttk.Frame
và khởi tạo các widget trực tiếp trên frame, giúp mã nguồn trở nên gọn gàng và dễ quản lý hơn. Việc sử dụng lớp con của ttk.Frame
trong cửa sổ chính của ứng dụng Tkinter không chỉ giúp bạn xây dựng các giao diện phức tạp một cách hiệu quả mà còn làm tăng khả năng tái sử dụng và mở rộng của mã nguồn. Đây là một kỹ thuật quan trọng trong lập trình hướng đối tượng, đặc biệt hữu ích khi phát triển các ứng dụng GUI với Tkinter.