voxeloctree
voxeloctree

Reputation: 849

Python Classes in Tkinter's Grid Manager

I am having a problem with either Tkinter's GRID geometry manager or custom classes or both. Most likely both. Here's the code:

import sys
from tkinter import 

def main():
    app = App()
    app.master.title("Sample application")
    app.mainloop()

class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid(sticky=N+S+E+W)

        top = self.winfo_toplevel()
        top.rowconfigure(0, weight=1)
        top.columnconfigure(0, weight=1)

        self.rowconfigure(1, weight=1)
        self.columnconfigure(0, weight=1)
        self.__createWidgets()

    def __createWidgets(self):
        self.f1 = Frame(self, height=100, width=200,
            bg='green')
        self.f1.grid(row=0, column=0, sticky=E+W)

        self.f2 = Frame( self, bg= "yellow", height=100, width=200 ) ############################# CHANGE to self.f2 = myTestFrame( self )
        self.f2.grid(row=1, sticky = N+S+E+W)

        self.f3 = Frame( self, bg = "cyan", height = 100, width = 200 )
        self.f3.grid(row=2, sticky = E+W)

        self.quitButton = Button ( self, text="Quit", command=self.quit )
        self.quitButton.grid(row=4, column=0, columnspan=100,
            sticky=E+W)

class myTestFrame( Frame ):
    def __init__( self, parent):
        Frame.__init__(self, None)

        self.myText = Text( self )
        self.myText.grid()

        #self.testFrame = Frame ( self, bg = "white", height = 100, width = 300 )
        #self.testFrame.grid()

if __name__ == "__main__":
    main()

`

Now here's the problem: This piece of code does everything I want it to do. There are three frames here, the top frame self.f1, the middle frame self.f2, the bottom frame self.f3, and a simple quit button. Top (row 0) and bottom (row 2) frames resize horizontally (column 0) and the middle frame's row (row 1, column 0) receives all of the weight for resizing horizontally and vertically. Everything is good... UNTIL I try to implement my own class myTestFrame.

Whenever I try to populate a custom frame in self.f2 with say a Text() widget, things go haywire. It displays the default text widget but my resizing goes funky, GRID placement is crazy. What is going on?

EDIT!!! unutbu's answer below certainly helps with the class issue. Now the GRID manager is placing a text widget correctly inside the middle frame self.f2, however, even when I set the sticky in myText.grid(sticky = N+S+E+W) it does not expand correctly. So I thought the following:

1) By setting the root window to be resizable with the def __init__ constructor of class App, I set it so that the first row and zeroth column of the App window would receive all of the space allotment for resizing in self.rowconfigure( 1, weight = 1) and self.columnconfigure( 0, weight = 1).

2) Now that the frame self.f2 is placed in row 1, it will receive all of the resizing with self.f2.grid(N+S+E+W).

3) Now I populate this custom frame with a text() widget that is set to occupy ALL of the space in this frame by stating self.myText.grid( sticky = N+S+E+W).

But the text() widget is not filling self.f2! When I do this normally without a custom class, using the sticky = N+S+E+W attribute works correctly. Am I thinking about this correctly?

Upvotes: 2

Views: 6864

Answers (1)

unutbu
unutbu

Reputation: 879729

The Frame.__init__ needs to be passed the parent:

class myTestFrame( tk.Frame ):
    tk.Frame.__init__(self, parent, *args, **kwargs)

Runnable example:

import sys
import Tkinter as tk
E=tk.E
W=tk.W
N=tk.N
S=tk.S
def main():
    app = App()
    app.master.title("Sample application")
    app.mainloop()

class App(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.grid(sticky=N+S+E+W)

        top = self.winfo_toplevel()
        top.rowconfigure(0, weight=1)
        top.columnconfigure(0, weight=1)

        self.rowconfigure(1, weight=1)
        self.columnconfigure(0, weight=1)
        self.__createWidgets()

    def __createWidgets(self):
        self.f1 = tk.Frame(self, height=100, width=200, bg='green')
        self.f1.grid(row=0, sticky=E+W)

        self.f2 = myTestFrame(self, bg='yellow', height=100, width=200)

        self.f3 = tk.Frame( self, bg = "cyan", height = 100, width = 200)
        self.f3.grid(row=2, sticky=E+W)

        self.quitButton = tk.Button(self, text="Quit", command=self.quit)
        self.quitButton.grid(row=4, column=0, sticky=E+W)

class myTestFrame( tk.Frame ):
    def __init__(self, parent, cnf={}, **kw):
        tk.Frame.__init__(self, parent, cnf, **kw)
        self.grid(row=1, sticky=N+S+E+W)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)                
        self.myText = tk.Text(self)
        self.myText.grid(row=0, sticky=N+S+E+W)

if __name__ == "__main__":
    main()

Upvotes: 5

Related Questions