Today we’ll look at how to code a minimal OOP window with a minimal OOP frame containing a minimal OOP label. It might not seem like much, but we’ll discover a number of interesting things along the way.
And Now, a Widget within a Widget within a Widget
Here’s what the code looks like:
from *tkinter* import * from *tkinter* import ttk def main(): window = Window() window.mainloop() class Window(Tk): def __init__(self): super().__init__() # object attributes self.mainframe = MainFrame(self) # configure #populate self.mainframe.grid() class MainFrame(ttk.Frame): def __init__(self, window): super().__init__(window) # object attributes self.label = Label(self) # configure # populate self.label.grid() class Label(ttk.Label): def __init__(self, parent): super().__init__(parent, text = "This is a label inside a frame inside a window.") if __name__ == "__main__": main()
Breakdown - The Window Class
import line is the same one we’ve been using all along. However, the second (
from *tkinter* import ttk) takes us into new territory. It gives us access to the updated
In short, these widgets take on the visual appearance closer to that of the operating system your script is run on. Not all widgets have a
ttk version and perhaps they never will. But, if you use ttk widgets and they still look dated, you can tell your users that it’s not your fault.
Populating the Window Class
First, we define the child:
self.mainframe = MainFrame(self)
Here we see what we were talking about last time. The parent identifies itself to tkinter as parent to the child widget being defined. That’s the right side of the equation. On the left, we use
self to make sure we can access the
mainframe attribute from any Window class methods we may write.
Because the layout of this demo isn’t complicated, we’ll let the children take care of their own
Breakdown - The Mainframe Class
class MainFrame(ttk.Frame): def __init__(self, window): super().__init__(window) # object attributes self.label = Label(self) # configure self.grid()
As usual, the first statement in
__init__() calls the super-class constructor and passes along the parent. This is the line I’m talking about:
Next, we see this line:
self.label = Label(self)
Which is a repeat of what happened in the Window class, but with a different child widget.
Lastly, we do the layout stuff:
Easy-peasey. Nothing complex about that layout.
Breakdown - Label Class
class Label(ttk.Label): def __init__(self, parent): super().__init__(parent, text = "This is a label inside a frame inside a window.")
By now, I’m sure you’re seeing the repetitiveness in these classes. Dull they may be, but by keeping them consistent, we make things easy on ourselves… they’re easy to understand, expand, and modify to suit a specific purpose. If we don’t have to spend even a moment understanding how a class is defined, we get to spend more time and energy doing the fun stuff and nailing down those bits of code that will be inevitably be tough.
The call to
super().__init__() breaks with site conventions we’ve established, but it’s done in the name of taking things one step at a time. The second argument tells tkinter what we want the label to say. In later examples, we’ll do those things after the fact in the
And that brings us to the end of another post. Hope you enjoyed it, hope it was helpful, and if you’re so inclined, you’re free to become our newest sponsor… like it says below.
Take care and next time we’ll do some
Please feel free to accept this invitation to become our newest sponsor.
And have a great day!
Comments? Questions? Observations?
Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
- You can also click the link below to email us,
- follow us on the Tkooper Facebook page, or
- You can subscribe via RSS so you won't miss anything.
Thank you very much for dropping by!
© Copyright 2021 Ronald V. Tarrant