You would want to configure the rows/columns to have weight
so they can expand when you resize the window. Also, you want the widgets to by sticky
to the sides of their cells. Not only do the frame
rows/columns need weight
, but so do all of the rows and columns within frame
, hence the for
loops.
from Tkinter import *
class MyFrame(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid(row=0, column=0, sticky=N+S+E+W)
#Give the grid, column of the frame weight...
Grid.rowconfigure(master, 0, weight=1)
Grid.columnconfigure(master, 0, weight=1)
self.create_widgets()
def create_widgets(self):
#Give the grid, column of each widget weight...
for rows in xrange(3):
Grid.rowconfigure(self, rows, weight=1)
for columns in xrange(1):
Grid.columnconfigure(self, columns, weight=1)
self.label = Label(self, text="This is a test")
self.label.grid(row=0, column=0, sticky=N+S+E+W)
self.mytext1 = Text(self, width=30, height=5)
self.mytext1.grid(row=1, column=0, sticky=N+S+E+W)
self.mytext2 = Text(self, width=30, height=5)
self.mytext2.grid(row=2, column=0, sticky=N+S+E+W)
root = Tk()
app = MyFrame(root)
root.mainloop()
Your basic frame
looks like this:
from Tkinter import *
#Sets up a frame
class MyApplication(Frame):
#When a class is initialized, this is called as per any class
def __init__(self, master):
#Similar to saying MyFrame = Frame(master)
Frame.__init__(self, master)
#Puts the frame on a grid. If you had two frames on one window, you would do the row, column keywords (or not...)
self.grid()
#Function to put the widgets on the frame. Can have any name!
self.create_widgets()
def create_widgets(self):
label = Label(self, text='Hello World!')
label.grid()
button = Button(self, text='Press Me!', command=self.hello)
button.grid()
def hello(self):
print "Hello World!"
root = Tk()
app = MyApplication(root)
root.mainloop()
Any Tkinter widget can be treated like this allowing for templates (I had a program where I needed multiple entries with the same behavior (click on clears the default text, click off returns it if nothing was entered) and instead of adding the bindings to each one, I was able to create a class of entries that acted the same) and easy implementation of toplevels
(additional windows). Here is an example of a more complex program:
class IntroScreen(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.title('Intro Screen')
self.create_widgets()
self.focus_force()
def create_widgets(self):
label = Label(self, text='Hello World!')
label.grid()
button = Button(self, text='Open Window', command=self.newWindow)
button.grid()
def newWindow(self):
self.toplevel = InfoWindow()
#Like the frame, or any widget, this inherited from the parent widget
class InfoWindow(Toplevel):
def __init__(self):
Toplevel.__init__(self)
self.grid()
self.create_widgets()
self.focus_force()
def create_widgets(self):
label = Label(self, text='This is a window!')
label.grid()
root = Tk()
app = IntroScreen(root)
root.mainloop()
As you can see, this has added functionality that would be much more difficult without classes. Look for more answers on stackoverflow (I recommend Bryan Oakley's numerous and informative answers) and do some research online if you intend on going further into Tkinter's powerful functionality!
PS: Here's a good place to start: Switch between two frames in tkinter