0

I am using this code to navigate between frames in my Tkinter text editor app. And when I want to organize the pageone with multiple frames in order to collect all the buttons in the same frame and other widgets in some other possible frames I got an error: _tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack. if you could help me, ty.

here is the code I used

import tkinter as tk
from tkinter import ttk

LARGE_FONT=("Verdana",12)

def popupmsg(msg):
    popup=tk.Tk()
    popup.wm_title("!")
    label=ttk.Label(popup,text=msg,font=LARGE_FONT)
    label.pack()
    b1=ttk.Button(popup,text="OKAY",command=popup.destroy)
    b1.pack()
    popup.mainloop()


class MainWindow(tk.Tk):

    def __init__(self,*arg,**kwargs):

        tk.Tk.__init__(self,*arg,**kwargs)

        container=tk.Frame(self)
        container.pack(side="top",fill="both",expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        menubar=tk.Menu(container)
        filemenu=tk.Menu(menubar,tearoff=0)
        filemenu.add_command(label="Save settings", command=lambda:popupmsg("Not supported yet!"))
        filemenu.add_command(label="Exit",command=quit)
        menubar.add_cascade(label="File", menu=filemenu)
        tk.Tk.config(self,menu=menubar)




        self.frames={}
        for F in(StartPage,PageOne):
            frame=F(container,self)
            self.frames[F]=frame
            frame.grid(row=0,column=0,sticky="nsew")
            self.show_frame(StartPage)

    def show_frame(self,cont):
        frame=self.frames[cont]
        frame.tkraise()

class StartPage(tk.Frame):

    def __init__(self,parent,controller):
        tk.Frame.__init__(self,parent)
        label_startpage=ttk.Label(self,text="Start Page",font=LARGE_FONT)
        label_startpage.pack(padx=10,pady=10)
        button_to_pageONE=ttk.Button(self,text="Go to Page ONE",command= lambda: 
controller.show_frame(PageOne)).pack()


class PageOne(tk.Frame):

    def __init__(self,parent,controller):
        tk.Frame.__init__(self,parent)
        self.rowconfigure(0, minsize=200, weight=1)
        self.columnconfigure(1, minsize=200, weight=1)

        txt_edit = tk.Text(self).grid(row=0, column=1, sticky="nsew")
        button_frame = tk.Frame(self,bg="lightblue").grid(row=0, column=0, sticky="ns")
        btn_open = ttk.Button(button_frame, text="Open").grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        btn_save = ttk.Button(button_frame, text="Save As...").grid(row=1, column=0, sticky="ew", padx=5)
        button_to_startpage = ttk.Button(button_frame, text="Back to Start Page",
                                     command=lambda: 
controller.show_frame(StartPage)).grid(row=2, column=0,
                                                                                            
sticky="ew", padx=5,
                                                                                             
pady=5)





app=MainWindow()
app.geometry("1280x720")
app.mainloop()

2 Answers2

0

You cannot use pack as well as grid on container

    container=tk.Frame(self)
    container.pack(side="top",fill="both",expand=True)
    container.grid_rowconfigure(0, weight=1)
    container.grid_columnconfigure(0, weight=1)

pack and grid just don't work well together. See this entry for more info

ohmchen
  • 69
  • 3
  • 1
    While it's true you can't use pack and grid on widgets that have the same parent, that's not what the code you posted is doing. It's using `pack` to place the container in it's parent, but the `grid_rowconfigure` and `grid_columnconfigure` only affect children of the container which is perfectly acceptable. – Bryan Oakley Apr 04 '21 at 22:23
0

You're making a very common mistake on this line:

button_frame = tk.Frame(self,bg="lightblue").grid(row=0, column=0, sticky="ns")

Because you are doing tk.Frame(...).grid(...), button_frame is being set to the result of .grid(...). That makes button_frame None. When you do btn_open = ttk.Button(button_frame, ...), that places the button as a child of the root window rather than a child of button_frame. You're using pack in the root window, so you can't use grid for any other widgets in the root window.

The solution is to properly create button_frame by separating widget creation from widget layout:

button_frame = tk.Frame(...)
button_frame.grid(...)
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685