Summary: in this tutorial, you’ll learn how to inherit from the ttk.Frame
class and use it in the root window.
In the previous tutorial, you’ve learned how to subclass the Tkinter.Tk
class. However, a Tkinter application should have only one Tk
instance.
Therefore, it’s common to inherit from the ttk.Frame
class and use the subclass in the root window.
To inherit the ttk.Frame
class, you use the following syntax:
class MainFrame(ttk.Frame):
pass
Code language: Python (python)
Since a Frame
needs a container, you need to add an argument to its __init__()
method and call the __init__()
method of the ttk.Frame
class like this:
class MainFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
Code language: Python (python)
The following shows the complete MainFrame
class that has a label and a button. When you click the button, it shows a message box:
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!')
Code language: Python (python)
The following defines an App
class that inherits from the Tk
class:
class App(tk.Tk):
def __init__(self):
super().__init__()
# configure the root window
self.title('My Awesome App')
self.geometry('300x100')
Code language: Python (python)
And you can bootstrap the application via the if __name__ == "__main__"
block.
if __name__ == "__main__":
app = App()
frame = MainFrame(app)
app.mainloop()
Code language: Python (python)
In this code:
- First, create a new instance of the
App
class. - Second, create a new instance of the
MainFrame
class and set its container to the app instance. - Third, start the application by calling the app(). It’ll execute the
__call__()
method that will invoke themainloop()
of the root window.
Put it all together:
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()
Code language: Python (python)
Output:
More Object-oriented Frame example
The following example uses the classes to convert the Replace window from the Frame
tutorial:
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()
Code language: Python (python)
Summary
- Subclass the
ttk.Frame
and initialize the widgets on the frame. - Use the subclass of the
ttk.Frame
in a root window.