1

I have a very primitive GUI built with Tkinter. This is my first attempt at a GUI so I am struggling to understand what is going on (and with syntax). Here is what I have:

from __future__ import division, print_function

import os, ttk, tkFileDialog, Tkconstants
import Tkinter as tk
import datetime as dt

Tkinter = tk

# define OS version
version = '0.0.2'

class TestGUI(tk.Tk):
    def __init__(self,parent):
        tk.Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

        # try building list of instruments and sites
        if os.path.isfile('config'):
            with open(''config','r') as config:
                config = dict( [(r.split('=')[0].strip(), r.split('=')[1].strip()) for r in config.read().split('\n') if r[0]<>'#'] )
            self.datapath = config['datapath']
        else:
            self.datapath = '../'


    def initialize(self):
        self.grid()

        # set up tabs
        self.geometry( "%dx%d+%d+%d" % (1500, 900, 200, 50) )
        nb = ttk.Notebook(self)
        nb.pack(fill='both',expand='yes')

        f1 = tk.Frame(bg='green')
        f2 = tk.Frame(bg='blue')
        f3 = tk.Frame(bg='red')

        f1.grid()
        f2.grid()
        f3.grid()

        nb.add(f1, text='General'.ljust(12,' '))
        nb.add(f2, text='Plot'.ljust(12,' '))
        nb.add(f3, text='Analysis'.ljust(12,' '))

        button = tk.Button(f2,text='I AM A BUTTON!')
        button.pack(side='left', anchor='nw', padx=3, pady=5)

        # insert button and text box for specifying data location       
        path_button = tk.Button(f1,text='Browse',command=self.askdirectory).pack(side='left', anchor='nw', padx=10, pady=15)


        self.path_entry = tk.StringVar()
        self.entry = tk.Entry(f1,textvariable=self.path_entry)
        self.entry.grid(column=12,row=8,columnspan=10)
        self.entry.bind("<Return>", self.OnPressEnter)
        self.path_entry.set(u"Sites directory path...")




    def OnButtonClick(self):
        print("You clicked the button !")

    def OnPressEnter(self,event):
        print("You pressed enter !")

    def askdirectory(self):
       """Returns a selected directoryname."""
       self.datapath = tkFileDialog.askdirectory()
       self.path_entry.set(self.datapath)


if __name__ == "__main__":
    app = TestGUI(None)
    app.title(version)
    app.mainloop()

My problem is centered around the addition of an entry box here:

 self.path_entry = tk.StringVar()
 self.entry = tk.Entry(f1,textvariable=self.path_entry)
 self.entry.grid(column=12,row=8,columnspan=10)
 self.entry.bind("<Return>", self.OnPressEnter)
 self.path_entry.set(u"Sites directory path...")

If I run the code as-is, it just hangs (it also hangs if I use "f2"; I suspect it is getting caught in the infinite loop without actually doing anything). However, if I change the parent from "f1" to "f3" or it works (the entry box is now in frame 3 instead of frame 1, but it at least does not hang on me). There is another issue even when f3 is used: the entry box's width/position never change despite my changing of column/row/columnspan values.

Does anyone know why the code is hanging when I specify "f1" or "f2" and how to fix it?

Does anyone know why my entry box position/size is not changing?

tnknepp
  • 5,888
  • 6
  • 43
  • 57

1 Answers1

3

You have put widgets in f1 and f2 using the pack geometry manager:

button = tk.Button(f2,text='I AM A BUTTON!')
button.pack(side='left', anchor='nw', padx=3, pady=5)
#and
path_button = tk.Button(f1,text='Browse',command=self.askdirectory).pack(side='left', anchor='nw', padx=10, pady=15)

Mixing geometry managers can lead to your program hanging, so using grid to put in the Entry does exactly that.

From effbot.org:

Warning: Never mix grid and pack in the same master window. Tkinter will happily spend the rest of your lifetime trying to negotiate a solution that both managers are happy with. Instead of waiting, kill the application, and take another look at your code. A common mistake is to use the wrong parent for some of the widgets.


The problem you describe of the Entry not changing position is because it is the only widget there, so the row(s) and column(s) in which the entry is are the only ones which do not have a width and height of 0. To make rows and columns without widgets take up space, use grid_rowconfigure(index, weight=x) where x is non-zero. An example is given in this answer.

Again from effbot.org:

weight=
A relative weight used to distribute additional space between rows. A row with the weight 2 will grow twice as fast as a row with weight 1. The default is 0, which means that the row will not grow at all.

fhdrsdg
  • 10,297
  • 2
  • 41
  • 62
  • That is great, thanks. When I create a new tab is it good practice to take a similar approach to the link you posted and create a gridded space that has pre-defined grid sizes? I am just wondering if my GUI layout will become disorganized without this, is that true? – tnknepp Nov 26 '14 at 14:05
  • That depends completely on what you want to put into the tab, but I think normally you shouldn't need to do this. For a little more explanation about which layout manager to use see [this answer](http://stackoverflow.com/a/14853514/3714930) by Bryan Oakley. Another thing I learned from reading his answers is that it's very useful to check resizing properties of frames and widgets by giving them distinct background colors, and not to continue until this works as desired. This can save you a lot of work later on. And of course, think about what you want your layout to be before making it. – fhdrsdg Nov 26 '14 at 14:24