Question

I'm trying to build a basic GUI using ttk / Tkinter.

I have a plotted out a basic GUI that has the right basic components, but when I try and prettify it / space it out, I'm reach my limit of getting ttk containers to play nicely...

Examples:

from Tkinter import *
import ttk

class MakeGUI(object):
    def __init__(self,root):
        self.root = root
        self.root.title("Text Comparitor")
        ## build frame
        self.mainframe = ttk.Frame(self.root, padding="3 3 12 12")
        self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
        self.mainframe.columnconfigure(0, weight=1)
        self.mainframe.rowconfigure(0, weight=1)
        self.mainframe.pack()
        ## text labels
        ttk.Label(self.mainframe, text="Conversion Truth Tester", font=("Helvetica", 32)).grid(column=1, row=1, sticky=E)
        self.mainframe.pack(side="bottom", fill=BOTH, expand=True)
        self.mainframe.grid()
        ttk.Label(self.mainframe, text="Source Filename:").grid(column=1, row=2, sticky=W)
        ttk.Label(self.mainframe, text="Source Text:").grid(column=1, row=3, sticky=W)
        ttk.Label(self.mainframe, text="Converted Text:").grid(column=1, row=4, sticky=W)
        ttk.Label(self.mainframe, text="Cleaned Source:").grid(column=1, row=5, sticky=W)
        ttk.Label(self.mainframe, text="Cleaned Converted:").grid(column=1, row=6, sticky=W)
        ttk.Label(self.mainframe, text="Details:").grid(column=1, row=7, sticky=W)
        ## buttons
        self.close = ttk.Button(self.mainframe, text="Close",command=self.closeFrame).grid(column=1, row=9, sticky=SE)
        self.next = ttk.Button(self.mainframe, text="Next",command=self.nextPara).grid(column=1, row=9, sticky=S)
        self.next = ttk.Button(self.mainframe, text="Prev",command=self.prevPara).grid(column=1, row=9, sticky=SW)

    def closeFrame(self):
        self.root.destroy()

    def nextPara(self):
        pass

    def prevPara(self):
        pass

def main():
    root = Tk()
    makeGUI = MakeGUI(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Which results in: http://imgur.com/a/CwpCU#0

I've been trying to add a 2nd container object, a label frame to hold the text label objects, which results in the buttons moving further up (and so I assume I'm not referencing the labelframe into the grid properly:

from Tkinter import *
import ttk

class MakeGUI(object):
    def __init__(self,root):
        self.root = root
        self.root.title("Text Comparitor")
        ## build frame
        self.mainframe = ttk.Frame(self.root, padding="3 3 12 12")
        self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
        self.mainframe.columnconfigure(0, weight=1)
        self.mainframe.rowconfigure(0, weight=1)
        self.mainframe.pack()
        ## text labels
        ttk.Label(self.mainframe, text="Conversion Truth Tester", font=("Helvetica", 32)).grid(column=1, row=1, sticky=E)
        self.lfdata = ttk.Labelframe(self.root, labelwidget=self.mainframe, text='Label')#
        self.lfdata.grid()
        ttk.Label(self.lfdata, text="Source Filename:").grid(column=1, row=2, sticky=W)
        ttk.Label(self.lfdata, text="Source Text:").grid(column=1, row=3, sticky=W)
        ttk.Label(self.lfdata, text="Converted Text:").grid(column=1, row=4, sticky=W)
        ttk.Label(self.lfdata, text="Cleaned Source:").grid(column=1, row=5, sticky=W)
        ttk.Label(self.lfdata, text="Cleaned Converted:").grid(column=1, row=6, sticky=W)
        ttk.Label(self.lfdata, text="Details:").grid(column=1, row=7, sticky=W)

        ## buttons
        self.close = ttk.Button(self.mainframe, text="Close",command=self.closeFrame).grid(column=1, row=9, sticky=SE)
        self.next = ttk.Button(self.mainframe, text="Next",command=self.nextPara).grid(column=1, row=9, sticky=S)
        self.next = ttk.Button(self.mainframe, text="Prev",command=self.prevPara).grid(column=1, row=9, sticky=SW)

    def closeFrame(self):
        self.root.destroy()

    def nextPara(self):
        pass

    def prevPara(self):
        pass

def main():
    root = Tk()
    makeGUI = MakeGUI(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Which results in: http://imgur.com/a/CwpCU#1 Note the swap of positions between buttons abd labels, and the just about visible aspects of the labelframe.

I'm trying to get the 2nd version to 'look' like a prettier version of the 1st.

Any pointers - I've been reading around the various resources / docs, and can't find anything that fits my example (most likely - I'm doing something silly...) and nothing I've tried has worked yet - including pack(), grid() and other snippets I've found in other related examples.

Was it helpful?

Solution

There are many places that require adjustments, let us comment on them (I will probably forget about something, so be sure to check the code at bottom).

First of all, applying weights to columns/rows in the frame alone is not going to make it expand as you resize the window. You need to do it in root. After that you might want to do it in the frame, to match your expectations about the layout after a resize. In your case, what makes most sense is making every column have the same weight > 0 and only making the second row have weight > 0. The reasoning for the columns is that you have 3 buttons, and you will want them all to expand in the free space in the same way. For the second part, that is a direct observation considering that you have a Labelframe at the second row. Giving a weight > 0 for any other row is going to give you a very weird layout. Weighting issues done.

Next thing I observed was your top label with a larger font. You certainly want it to span 3 columns (again, this number 3 is related to the row of buttons you will create at a later time). You may also want the text to be centered in these 3 columns (I'm not sure about your preferences here).

Now the Labelframe you create. It is just wrong, the labelwidget option does not mean what you think it does. It specifies a Label widget to serve as the label for this label frame. Thus, specifying your main frame for this parameter makes no sense. Maybe you want to specify some text to be visible at a certain position in the label frame. Also, this label frame must be grided with a columnspan of 3 too.

For the "gridding" in general I recommend specifying the option in_, so you make clear in relation to what widget you are "gridding". With that, it becomes obvious to start at column=0, row=0 each time you deepen your widget parenting level.

Here is how I adjusted your code:

import Tkinter
import ttk

class MakeGUI(object):
    def __init__(self,root):
        self.root = root
        self.root.title(u"Title")
        ## build frame
        self.mainframe = ttk.Frame(self.root, padding=(6, 6, 12, 12))
        self.mainframe.grid(sticky='nwse')
        for column in range(3):
            self.mainframe.columnconfigure(column, weight=1)
        self.mainframe.rowconfigure(1, weight=1)

        ## text labels
        ttk.Label(self.mainframe, text=u"Label Title", anchor='center',
                font=("Helvetica", 32)).grid(in_=self.mainframe,
                        column=0, row=0, columnspan=3, sticky="ew")

        self.lfdata = ttk.Labelframe(self.mainframe, padding=(6, 6, 12, 12),
                text='Labelframe')
        self.lfdata.grid(column=0, columnspan=3, row=1, sticky='nsew')
        info = (u"Source Filename", u"Source Text", u"Converted Text",
                u"Cleaned Source", u"Cleaned Converted", u"Details")
        for i, item in enumerate(info):
            ttk.Label(self.lfdata, text=u"%s:" % item).grid(in_=self.lfdata,
                    column=0, row=i, sticky='w')

        ## buttons
        btn = (u"Close", u"Next", u"Prev")
        for i, item in enumerate(btn):
            ttk.Button(self.mainframe, text=item).grid(in_=self.mainframe,
                    column=i, row=3)

def main():
    root = Tkinter.Tk()
    root.columnconfigure(0, weight=1)
    root.rowconfigure(0, weight=1)
    makeGUI = MakeGUI(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Here is how it looks when the program starts and after some resizing:

enter image description here enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top