Объектно-ориентированные фреймы Tkinter в Python: класс ttk.Frame
Ранее вы узнали, как создать подкласс класса 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()