2
votes

Made a simple grid-based Tkinter Frame subclass today. It's master is a Tk() object.

root = Tk()
root.title('Rep Logger UI')
root.geometry('500x500')

mother = rep_ui(master=root)
mother.mainloop()

All I wanted to do was divide the rep_ui window into two frames ( red, blue ) of equal width, and then put a few widgets in each.

But I'm not doing something right. The red+blue frames don't completely fill the window. Either they're not fully-filling the rep_ui class, or the rep_ui class isn't expanding properly inside its master (root) ?

Also, the blue and red frames are of different width, even though I column-configured them with the same weight-s.

def __init__(self, master=None):
    Frame.__init__(self, master)

    """to make the rep_ui frame expand into the entire OS window."""

    self.master.rowconfigure(    0, weight = 1 )              # outer-bounds' row[0] weight set
    self.master.columnconfigure( 0, weight = 1 )              # outer-bounds' col[0] weight set

    self.grid(sticky=W+E+N+S)                                 # EWNS-sticky mode set

    self.columnconfigure(        0, weight = 1 )              # column[0] weight set
    self.columnconfigure(        1, weight = 1 )              # column[1] weight set

    self.rowconfigure(           0, weight = 1 )              #    row[0] weight set
    self.rowconfigure(           1, weight = 1 )              #    row[1] weight set


    """ left and right frames"""
    self.fl = Frame(self, bg="red")                           # RED  Frame ( left )
    self.fr = Frame(self, bg="blue")                          # BLUE Frame ( right )

    self.fl.grid( row=0, column=0,  sticky=N+S+W+E)           # .grid() RED  one
    self.fr.grid  row=0, column=1,  sticky=N+S+W+E)           # .grid() BLUE one

Here is a picture of the problem I'm describing: http://imgur.com/MkSE9yt

3

3 Answers

3
votes

Why are these windows different widths?

The reason is pretty obvious: There's a text widget inside the red frame. The problem is that you added the weight parameter to both frames, but not to the widgets inside. For the text, you could use somethng like

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

Why does this blank space exist?

That's because you configured the row 1 here:

self.rowconfigure(1, weight=1)

Though it's not used, it will appear. Remove or comment this line out to make it work.

1
votes

The weight parameter only affects how extra space is distributed. I.e. the grid manager first grids all the "grandchild" widgets, then if there is extra space, distributes it to the child widgets according to the supplied weights. (documented here: the weight parameter "gives the relative weight of this column or row when distributing the extra space")

A visual explanation: Diagram showing extra space distribution

As for the blank space at the bottom, I think we need to see the rest of the code to figure that out.

-2
votes

You can try using the place geometry manager:

self.fl.place( relx = 0.0, rely = 0.0, relwidth = 0.5, relheight = 1.0 )
self.fr.place( relx = 0.5, rely = 0.0, relwidth = 0.5, relheight = 1.0 )

Using parent-widget relative scales is rather powerful, though still simple to code and validate and future-proof for re-scaling UI and does not suffer from other artifacts and unintended side-effects a complex UI-design may encounter during its life-cycle.

enter image description here

root = Tkinter.Tk()
aLF  = Tkinter.Frame(  root, bg = "red" )
aRF  = Tkinter.Frame(  root, bg = "blue")
aLF.place(                   relx = 0.0,
                                 rely = 0.0, relwidth = 0.5, relheight = 1.0 )
aRF.place(                   relx = 0.5,
                                 rely = 0.0, relwidth = 0.5, relheight = 1.0 )
aTextR = Tkinter.Label( aRF, bg = "white", text = "aFR := frame right" )
aTextR.place(                relx = 0.0,
                                 rely = 0.0 )
aTextL = Tkinter.Label( aLF, bg = "white", text = "aFL := frame left" )
aTextL.place(                relx = 0.0,
                                 rely = 0.0 )
root.title( 'Rep Logger UI')
root.geometry( '500x500' )
root.lift()

and cross-validate

root.geometry( '500x500' )
root.geometry( '300x100' )
root.geometry( '400x300' )
root.geometry( '600x150' )