15

I'm trying to use the functionality from the Tkinter module (Python 2.7) to create a GUI that has eight widgets placed on a 7 row by 5 column grid (sorry that I did not include an image; the dialog box is not allowing me to browse and upload the saved image).

(Widget, start_row, start_col, row_span, column_span):

  1. ("Button 0", 6, 0, 1, 1)
  2. ("Button 1", 6, 1, 1, 1)
  3. ("Button 2", 6, 2, 1, 1)
  4. ("Button 3", 6, 3, 1, 1)
  5. ("Button 4", 6, 4, 1, 1)
  6. ("Frame1", 0, 0, 3, 2)
  7. ("Frame2", 2, 0, 3, 2)
  8. ("Frame3", 0, 3, 6, 3)

Yet, when I run my code, the buttons and Frame3 are rendered fine, but Frame1 vertically "squashes" Frame2. Any suggestions would be greatly appreciated. (I have read the suggested StackOverflow answers and none seem to provide information that can be used to solve my problem. Also, I have searched extensively online to no avail.)

from Tkinter import *

class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master.title("Grid Manager")

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

        for i in range(5):
            self.master.button = Button(master, text = "Button {0}".format(i))
            self.master.button.grid(row=6, column=i, sticky=W+E)

        self.Frame1 = Frame(master, bg="red")
        self.Frame1.grid(row = 0, column = 0, rowspan = 3, columnspan = 2, sticky = W+E+N+S) 
        self.Frame2 = Frame(master, bg="blue")
        self.Frame2.grid(row = 2, column = 0, rowspan = 3, columnspan = 2, sticky = W+E+N+S)
        self.Frame3 = Frame(master, bg="green")
        self.Frame3.grid(row = 0, column = 2, rowspan = 6, columnspan = 3, sticky = W+E+N+S)

root = Tk()
app = Application(master=root)
app.mainloop()

UPDATE: Now that I'm at my personal computer, here are images for the result that I want and the result that I get, respectively:

WANT

GET

Jubbles
  • 4,450
  • 8
  • 35
  • 47

3 Answers3

22

After messing around with my code for a few hours, I was finally able to create the GUI that I intended to. The key was looping over rows and columns and setting their weights using rowconfigure and columnconfigure, respectively. Code is below:

from tkinter import *

class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid()
        self.master.title("Grid Manager")

        for r in range(6):
            self.master.rowconfigure(r, weight=1)    
        for c in range(5):
            self.master.columnconfigure(c, weight=1)
            Button(master, text="Button {0}".format(c)).grid(row=6,column=c,sticky=E+W)

        Frame1 = Frame(master, bg="red")
        Frame1.grid(row = 0, column = 0, rowspan = 3, columnspan = 2, sticky = W+E+N+S) 
        Frame2 = Frame(master, bg="blue")
        Frame2.grid(row = 3, column = 0, rowspan = 3, columnspan = 2, sticky = W+E+N+S)
        Frame3 = Frame(master, bg="green")
        Frame3.grid(row = 0, column = 2, rowspan = 6, columnspan = 3, sticky = W+E+N+S)

root = Tk()
root.geometry("400x200+200+200")
app = Application(master=root)
app.mainloop()

enter image description here

Matthew Moisen
  • 16,701
  • 27
  • 128
  • 231
Jubbles
  • 4,450
  • 8
  • 35
  • 47
  • 5
    For anyone running this example the window initially has limited height and width and you have to resize it to confirm that the code works. Alternatively, give it a default geometry, `root.geometry("400x200+200+200")` (just after `root = Tk()`). – Andy G Aug 24 '15 at 23:04
4

Since frame 1, 2 and 3 don't have any widgets inside them and you haven't given them any height, their natural size will be one pixel tall. If you put something in frame2, or give frame2 a height, it will show up.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Isn't a frame a widget? Even if their height defaults to one pixel tall, I have specified a rowspan, columnspan, and have made them sticky in all directions, so why don't they expand when I resize the window? – Jubbles May 25 '11 at 23:38
  • 3
    @Jubbles: because only one row has a weight > 0. When you resize you create extra space, and that extra space is filled by widgets relative to their weight. Since only one row has a weight of 1 you're saying "I want 100% of the extra space to go to this row" – Bryan Oakley May 26 '11 at 10:51
  • I understand now. Your comment was very helpful. – Jubbles May 26 '11 at 13:33
1

If you like try pytkgen (https://github.com/tmetsch/pytkgen or http://pypi.python.org/pypi/pytkgen/) - which generates Tkinter GUIs from JSON files and takes care of the weight, height and row/columnconfigure. See the examples here: https://github.com/tmetsch/pytkgen/tree/master/examples

Andre
  • 97
  • 1