Search code examples
pythontkinterttk

Tkinter widgets are in the same row, but why aren't they appearing that way?


I am trying to make a start menu for a search engine. I am trying to have buttons and other widgets appear next to labels. This is my code:

class Application(tk.Tk): #subclass Tk
    '''Does most of the handling.'''
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.title("Academic Search")
        self.geometry("1000x600")
        self.resizable(width=True,height=True)
        self.start = Start(self)
        self.start.grid(sticky=(tk.E + tk.W + tk.N + tk.S))
        self.update_button = ttk.Button(self, text="Update Database", command=self.to_database)
        self.update_button.grid(row=0,column=0,sticky=tk.W)
        self.cc_button = ttk.Button(self, text="Find Common Citations",command=self.to_cc)
        self.cc_button.grid(row=1, column=0, sticky=tk.W)#, pady=20)
        self.search_button = ttk.Button(self, text="Search", command=self.search)
        self.search_button.grid(row=2, column=2, sticky=(tk.E))


class Start(tk.Frame): #subclass of Frame
    '''The start window'''
    def __init__(self, parent, *args, **kwargs): #takes same args as parent
        '''Initializes start window.'''
        super().__init__(parent, *args, **kwargs) #calls superclass constructor
        query = tk.StringVar()
        self.num_return = tk.IntVar()
        cw = tk.DoubleVar()
        cd = tk.IntVar()
        graph = tk.BooleanVar()
        jstor = tk.BooleanVar()
        self.mb_text = tk.StringVar()
        self.mb_text.set('Search multiple DOIs')
        self.num_return = tk.IntVar()
        self.search_box = ttk.Entry(parent, text='Enter one DOI:',textvariable=query)
        self.multiple_button = ttk.Button(self, textvariable=self.mb_text,command=self.to_mult)
        self.lbl = ttk.Label(self,text='Enter one DOI.')
        self.num_return_lbl = ttk.Label(self, text='Maximum number of records returned:')
        self.num_return_box = ttk.Entry(parent, textvariable=self.num_return)
        self.cw_lbl = ttk.Label(self, text='Citation weight (must be between 0 and 1):')
        self.cw_box = ttk.Spinbox(parent, from_=0, to=1, increment=0.01,textvariable=cw)
        self.cd_lbl = ttk.Label(self, text='Maximum citation distance (runtime will increase dramatically if greater than 3):')
        self.cd_box = ttk.Spinbox(parent, from_=1, to=10,increment=1, textvariable=cd)
        self.jstor_button = ttk.Checkbutton(parent, text='Use JSTOR (requires JSTOR Labs token)',command=jstor)
        self.graph_box = ttk.Checkbutton(parent, text='Graph', variable=graph)
        self.add_widgets()

    def add_widgets(self):
        '''Adds widgets to grid.'''
        self.lbl.grid(row=2, column=1, sticky=tk.E)
        self.cw_lbl.grid(row=3, column=1, sticky=tk.E)
        self.cw_box.grid(row=3, column=2, sticky=tk.E)
        self.cd_lbl.grid(row=4, column=1, sticky=tk.E)
        self.cd_box.grid(row=4, column=2, sticky=tk.E)
        self.num_return_lbl.grid(row=5, column=1, sticky=tk.E)
        self.num_return_box.grid(row=5, column=2, sticky=tk.E)
        self.search_box.grid(row=2, column=2, sticky=(tk.E+tk.W))
        self.graph_box.grid(row=6, column=2, sticky=tk.E)
        self.jstor_button.grid(row=7, column=2, sticky=tk.E)
        self.multiple_button.grid(row=9, column=0, sticky=(tk.W+tk.N))

Why aren't the labels in line with the other elements (Spinboxes, check buttons, entries) when they are in the same row?

This is what it looks like when I do mainloop():

screenshot of mainloop() running


Solution

  • The buttons and the labels have different parents, which is why they appear in different locations.

    You can see this very clearly if you give the Start frame a distinctive color. For example, change how you create Start to be like this:

    self.start = Start(self, background="red")
    

    You will end up with a window that looks like this:

    enter image description here

    Look at the first argument in each of these two lines of code. One uses self and one uses parent. self and parent are two different widgets.

        self.cw_lbl = ttk.Label(self, ...)
        self.cw_box = ttk.Spinbox(parent, ...)
    

    Everywhere you use parent as the parent of a widget in Start, you should change it to self. For example, the above code needs to be changed to:

    self.cw_box = ttk.Spinbox(self, ...)