Ранее вы узнали, как создать подкласс класса Tkinter.Tk. Однако приложение Tkinter должно иметь только один экземпляр Tk. Поэтому обычно наследуют от класса ttk.Frame и используют подкласс в корневом окне.
Как наследовать от класса ttk.Frame
Чтобы унаследовать класс ttk.Frame, используйте следующий синтаксис:
class MainFrame(ttk.Frame):
pass
Поскольку Frame нуждается в контейнере, вам необходимо добавить аргумент в его метод __init__() и вызвать метод __init__() класса ttk.Frame следующим образом:
class MainFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
Ниже показан полный класс MainFrame, который имеет метку и кнопку. При нажатии кнопки отображается окно сообщения:
class MainFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
options = {'padx': 5, 'pady': 5}
# label
self.label = ttk.Label(self, text="Hello, Tkinter!")
self.label.pack(**options)
# button
self.button = ttk.Button(self, text="Click Me")
self.button['command'] = self.button_clicked
self.button.pack(**options)
# show the frame on the container
self.pack(**options)
def button_clicked(self):
showinfo(title="Information",
message="Hello, Tkinter!")
Ниже определяется класс App, который наследуется от класса Tk:
class App(tk.Tk):
def __init__(self):
super().__init__()
# configure the root window
self.title('My Awesome App')
self.geometry('300x100')
И вы можете загрузить приложение через блок if __name__ == «__main__».
if __name__ == "__main__": app = App() frame = MainFrame(app) app.mainloop()
В этом коде:
- Сначала создайте новый экземпляр класса App.
- Во-вторых, создайте новый экземпляр класса MainFrame и установите его контейнер для экземпляра приложения.
- В-третьих, запустите приложение, вызвав app(). Оно выполнит метод __call__(), который вызовет mainloop() корневого окна.
Соединим все вместе:
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}
# label
self.label = ttk.Label(self, text="Hello, Tkinter!")
self.label.pack(**options)
# button
self.button = ttk.Button(self, text="Click Me")
self.button['command'] = self.button_clicked
self.button.pack(**options)
# show the frame on the container
self.pack(**options)
def button_clicked(self):
showinfo(title="Information",
message="Hello, Tkinter!")
class App(tk.Tk):
def __init__(self):
super().__init__()
# configure the root window
self.title('My Awesome App')
self.geometry('300x100')
if __name__ == "__main__":
app = App()
frame = MainFrame(app)
app.mainloop()
Выход:

Пример объектно-ориентированного фрейма
В следующем примере классы используются для преобразования окна Replace из учебника Frame:

import tkinter as tk
from tkinter import ttk
class InputFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
# setup the grid layout manager
self.columnconfigure(0, weight=1)
self.columnconfigure(0, weight=3)
self.__create_widgets()
def __create_widgets(self):
# 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)
# 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)
# Match Case checkbox
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)
# Wrap Around checkbox
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)
# setup the grid layout manager
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)
# windows only(remove the minimize/maximize button)
self.attributes('-toolwindow', True)
# layout on the root window
self.columnconfigure(0, weight=4)
self.columnconfigure(1, weight=1)
self.__create_widgets()
def __create_widgets(self):
# create the input frame
input_frame = InputFrame(self)
input_frame.grid(column=0, row=0)
# create the button frame
button_frame = ButtonFrame(self)
button_frame.grid(column=1, row=0)
if __name__ == "__main__":
app = App()
app.mainloop()
