Tkinter – How to create a custom Tkinter Frame object? I tried but it doesn't work

Question:

I tried to create some custom tkinter objects to build my GUIs easier but unfortunately I couldn’t. For example, what about if I want an object that identify a frame placed inside another one? To do that I wrote it:

Main code (file name: test.py):

import tkinter as tk
from tkinter import ttk
import ttk_plus as ttkp # my custom library

parent=tk.Tk()
parent.geometry("686x424+370+100")
parent.title("Test")
parent.configure(background="#f0f0f0")
parent.minsize(686, 424)

MyFrame=ttkp.Frame(parent) # my custom object
MyFrame.pack(padx=(5,5), pady=(5,5))

parent.mainloop() 

Library (file name: ttk_plus.py):

class Frame(tk.Frame):
    def __init__(self, container):
        super().__init__(container)
        
        self.container=container
        
        # definisco il frame principale:
        self.Frame1=tk.Frame(self.container, background="white")
        
        # definisco il frame secondario:
        self.Frame2=tk.Frame(self.Frame1, background="white", highlightbackground="red", highlightthickness=1)
        self.Frame2.pack(padx=(5, 5), pady=(5, 5), fill=tk.BOTH)

If I run test.py, the software start without any kind of issues, but I can’t see my object inside the main window. Where did I go wrong?

Asked By: TurboC

||

Answers:

In your custom frame, Frame1 is the parent of Frame2. You have packed Frame2 but not its parent, hence it’s simply not in your window.

Fix

Try to pack your Frame1:

self.Frame1=tk.Frame(self.container, background="white")
self.Frame1.pack(fill="both", expand=True)

And the result would be:
enter image description here

Just to check its working properly, try adding a sample button to the Frame2
enter image description here

Answered By: Billy

If you are creating a custom frame, every widget created in this frame needs to be a descendant of the frame, not the container. Otherwise, Frame will affect its parent in unexpected ways.

self.Frame1=tk.Frame(self, background="white")

You also need to make sure you call some geometry manager (pack, place, grid) on this inner frame. Otherwise, this frame and any widgets in it won’t be visible.

Since it’s the only direct child in the container, pack is the simplest:

self.Frame1.pack(fill="both", expand=True)

Finally, since at the moment you’re only creating frames, you’ll likely want to either give the frame a size, or use geometry manager attributes that cause it to fill the window.

MyFrame.pack(padx=(5,5), pady=(5,5), fill="both", expand=True)
Answered By: Bryan Oakley
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.