http://zetcode.com/gui/tkinter/layout/
Layout management in Tkinter
In this part of the Tkinter programming tutorial, we introduce layout managers.There are two kinds of widgets: containers and their children. The containers group their children into suitable layouts.
Tkinter has three built-in layout managers: the
pack, grid,
and place managers. The place geometry
manager positions widgets using absolute positioning. The pack geometry
manager organises widgets in horizontal and vertical boxes. The grid geometry
manager places widgets in a two dimensional grid.
Absolute positioning
In most cases, programmers should use layout managers. There are a few situations where we could use absolute positioning. In absolute positioning, the programmer specifies the position and the size of each widget in pixels. The size and the position of a widget do not change if we resize a window. Applications look different on various platforms, and what looks OK on Linux, might not look OK on Mac OS. Changing fonts in our application might spoil the layout. If we translate our application into another language, we must redo our layout.
absolute.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
In this script, we lay out images
using absolute positioning.
Author: Jan Bodnar
Last modified: July 2017
Website: www.zetcode.com
"""
from PIL import Image, ImageTk
from tkinter import Tk, BOTH
from tkinter.ttk import Frame, Label, Style
class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Absolute positioning")
self.pack(fill=BOTH, expand=1)
Style().configure("TFrame", background="#333")
bard = Image.open("bardejov.jpg")
bardejov = ImageTk.PhotoImage(bard)
label1 = Label(self, image=bardejov)
label1.image = bardejov
label1.place(x=20, y=20)
rot = Image.open("rotunda.jpg")
rotunda = ImageTk.PhotoImage(rot)
label2 = Label(self, image=rotunda)
label2.image = rotunda
label2.place(x=40, y=160)
minc = Image.open("mincol.jpg")
mincol = ImageTk.PhotoImage(minc)
label3 = Label(self, image=mincol)
label3.image = mincol
label3.place(x=170, y=50)
def main():
root = Tk()
root.geometry("300x280+300+300")
app = Example()
root.mainloop()
if __name__ == '__main__':
main()
In this example, we place three images using absolute positioning.
We use the place geometry manager.
from PIL import Image, ImageTkWe use
Image and ImageTk from the Python
Imaging Library (PIL) module.
style = Style()
style.configure("TFrame", background="#333")
We configure our frame to have a dark gray background using styles.
bard = Image.open("bardejov.jpg")
bardejov = ImageTk.PhotoImage(bard)
We create an image object and a photo image object from an image
in the current working directory.
label1 = Label(self, image=bardejov)We create a
Label with an image. Labels
can contain text or images.
label1.image = bardejovWe must keep the reference to the image to prevent image from being garbage collected.
label1.place(x=20, y=20)The label is placed on the frame at x=20 and y=20 coordinates.
Pack manager
Thepack geometry manager organises widgets in horizontal and vertical boxes.
The layout is controlled with the fill, expand, and side
options.
Buttons example
In the following example, we position two buttons in the bottom-right corner of the window. We use thepack manager.
buttons.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
In this script, we use the pack manager
to position two buttons in the
bottom-right corner of the window.
Author: Jan Bodnar
Last modified: July 2017
Website: www.zetcode.com
"""
from tkinter import Tk, RIGHT, BOTH, RAISED
from tkinter.ttk import Frame, Button, Style
class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Buttons")
self.style = Style()
self.style.theme_use("default")
frame = Frame(self, relief=RAISED, borderwidth=1)
frame.pack(fill=BOTH, expand=True)
self.pack(fill=BOTH, expand=True)
closeButton = Button(self, text="Close")
closeButton.pack(side=RIGHT, padx=5, pady=5)
okButton = Button(self, text="OK")
okButton.pack(side=RIGHT)
def main():
root = Tk()
root.geometry("300x200+300+300")
app = Example()
root.mainloop()
if __name__ == '__main__':
main()
We have two frames. There is the base frame and an additional frame,
which expands in both directions and push the two buttons to the
bottom of the base frame. The buttons are placed in a horizontal box and
placed to the right of this box.
frame = Frame(self, relief=RAISED, borderwidth=1) frame.pack(fill=BOTH, expand=True)We create another
Frame widget. This widget takes
the bulk of the area. We change the border of the frame so that
the frame is visible; by default it is flat.
closeButton = Button(self, text="Close") closeButton.pack(side=RIGHT, padx=5, pady=5)A
closeButton is created. It is put into a horizontal box.
The side parameter causes the button to be placed to the right
of the horizontal. The padx and the pady parameters
put some space between the widgets.
The padx puts some space between the button widgets and between the
closeButton and the right border of the root window. The
pady puts some space between the button widgets and the borders of
the frame and the borders of the root window.
okButton.pack(side=RIGHT)The
okButton is placed next to the closeButton with
5 px space between them.
Review example
Thepack manager is a simple layout manager. It can be used
to do simple layout tasks. In order to create more complicated layouts,
we need to utilise more frames, each having its own pack manager.
review.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
In this script, we use the pack manager
to position two buttons in the
bottom-right corner of the window.
Author: Jan Bodnar
Last modified: July 2017
Website: www.zetcode.com
"""
from tkinter import Tk, Text, TOP, BOTH, X, N, LEFT
from tkinter.ttk import Frame, Label, Entry
class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Review")
self.pack(fill=BOTH, expand=True)
frame1 = Frame(self)
frame1.pack(fill=X)
lbl1 = Label(frame1, text="Title", width=6)
lbl1.pack(side=LEFT, padx=5, pady=5)
entry1 = Entry(frame1)
entry1.pack(fill=X, padx=5, expand=True)
frame2 = Frame(self)
frame2.pack(fill=X)
lbl2 = Label(frame2, text="Author", width=6)
lbl2.pack(side=LEFT, padx=5, pady=5)
entry2 = Entry(frame2)
entry2.pack(fill=X, padx=5, expand=True)
frame3 = Frame(self)
frame3.pack(fill=BOTH, expand=True)
lbl3 = Label(frame3, text="Review", width=6)
lbl3.pack(side=LEFT, anchor=N, padx=5, pady=5)
txt = Text(frame3)
txt.pack(fill=BOTH, pady=5, padx=5, expand=True)
def main():
root = Tk()
root.geometry("300x300+300+300")
app = Example()
root.mainloop()
if __name__ == '__main__':
main()
The example shows how to create a more complex layout with multiple
frames and pack managers.
self.pack(fill=BOTH, expand=True)The first frame is the base frame, on which other frames are placed. Note that in addition to organising children within frames, we also manage the frames on the base frame.
frame1 = Frame(self) frame1.pack(fill=X) lbl1 = Label(frame1, text="Title", width=6) lbl1.pack(side=LEFT, padx=5, pady=5) entry1 = Entry(frame1) entry1.pack(fill=X, padx=5, expand=True)The first two widgets are placed on the first frame. The entry is horizontally streched with the
fill and the expand parameters.
frame3 = Frame(self) frame3.pack(fill=BOTH, expand=True) lbl3 = Label(frame3, text="Review", width=6) lbl3.pack(side=LEFT, anchor=N, padx=5, pady=5) txt = Text(frame3) txt.pack(fill=BOTH, pady=5, padx=5, expand=True)Inside the third frame, we place a label and a text widget. The label is anchored to the north. The text widget takes the whole remaining area.
Grid manager
The Tkinter'sgrid geometry manager is used to create a
skeleton of a calculator.
calculator.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
In this script, we use the grid manager
to create a skeleton of a calculator.
Author: Jan Bodnar
Last modified: July 2017
Website: www.zetcode.com
"""
from tkinter import Tk, W, E
from tkinter.ttk import Frame, Button, Entry, Style
class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Calculator")
Style().configure("TButton", padding=(0, 5, 0, 5),
font='serif 10')
self.columnconfigure(0, pad=3)
self.columnconfigure(1, pad=3)
self.columnconfigure(2, pad=3)
self.columnconfigure(3, pad=3)
self.rowconfigure(0, pad=3)
self.rowconfigure(1, pad=3)
self.rowconfigure(2, pad=3)
self.rowconfigure(3, pad=3)
self.rowconfigure(4, pad=3)
entry = Entry(self)
entry.grid(row=0, columnspan=4, sticky=W+E)
cls = Button(self, text="Cls")
cls.grid(row=1, column=0)
bck = Button(self, text="Back")
bck.grid(row=1, column=1)
lbl = Button(self)
lbl.grid(row=1, column=2)
clo = Button(self, text="Close")
clo.grid(row=1, column=3)
sev = Button(self, text="7")
sev.grid(row=2, column=0)
eig = Button(self, text="8")
eig.grid(row=2, column=1)
nin = Button(self, text="9")
nin.grid(row=2, column=2)
div = Button(self, text="/")
div.grid(row=2, column=3)
fou = Button(self, text="4")
fou.grid(row=3, column=0)
fiv = Button(self, text="5")
fiv.grid(row=3, column=1)
six = Button(self, text="6")
six.grid(row=3, column=2)
mul = Button(self, text="*")
mul.grid(row=3, column=3)
one = Button(self, text="1")
one.grid(row=4, column=0)
two = Button(self, text="2")
two.grid(row=4, column=1)
thr = Button(self, text="3")
thr.grid(row=4, column=2)
mns = Button(self, text="-")
mns.grid(row=4, column=3)
zer = Button(self, text="0")
zer.grid(row=5, column=0)
dot = Button(self, text=".")
dot.grid(row=5, column=1)
equ = Button(self, text="=")
equ.grid(row=5, column=2)
pls = Button(self, text="+")
pls.grid(row=5, column=3)
self.pack()
def main():
root = Tk()
app = Example()
root.mainloop()
if __name__ == '__main__':
main()
The grid manager is used to organize buttons in the frame container.
Style().configure("TButton", padding=(0, 5, 0, 5),
font='serif 10')
We configure the Button widget to have a specific
font and to have some internal padding.
self.columnconfigure(0, pad=3) ... self.rowconfigure(0, pad=3)We use the
columnconfigure() and the rowconfigure()
methods to define some space in grid columns and rows. This way we achieve that
the buttons are separated by some space.
entry = Entry(self) entry.grid(row=0, columnspan=4, sticky=W+E)The
Entry widget is where the digits are displayed. The widget
is placed in the first row and it spans all four columns. Widgets may
not occupy all the space allotted by cells in the grid. The sticky
parameter expands the widget in a given direction. In our case we ensure
that the entry widget is expanded from left to right.
cls = Button(self, text="Cls") cls.grid(row=1, column=0)The
cls button is placed in the second row and first column. Note that
the rows and columns start at zero.
self.pack()The
pack() method shows the frame widget and gives it initial size.
If no other parameters are given, the size will be just enough to show
all children. This method packs the frame widget to the toplevel root
window, which is also a container. The grid geometry manager is used to
organize buttons in the frame widget.
Windows example
The following example creates the windows dialog using thegrid geometry manager.
windows.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
In this script, we use the grid
manager to create a more complicated
layout.
Author: Jan Bodnar
Last modified: July 2017
Website: www.zetcode.com
"""
from tkinter import Tk, Text, BOTH, W, N, E, S
from tkinter.ttk import Frame, Button, Label, Style
class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Windows")
self.pack(fill=BOTH, expand=True)
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
lbl = Label(self, text="Windows")
lbl.grid(sticky=W, pady=4, padx=5)
area = Text(self)
area.grid(row=1, column=0, columnspan=2, rowspan=4,
padx=5, sticky=E+W+S+N)
abtn = Button(self, text="Activate")
abtn.grid(row=1, column=3)
cbtn = Button(self, text="Close")
cbtn.grid(row=2, column=3, pady=4)
hbtn = Button(self, text="Help")
hbtn.grid(row=5, column=0, padx=5)
obtn = Button(self, text="OK")
obtn.grid(row=5, column=3)
def main():
root = Tk()
root.geometry("350x300+300+300")
app = Example()
root.mainloop()
if __name__ == '__main__':
main()
In this example, we use a Label widget, a Text
widget, and four buttons.
self.columnconfigure(1, weight=1) self.columnconfigure(3, pad=7) self.rowconfigure(3, weight=1) self.rowconfigure(5, pad=7)We define some space among widgets in the grid. The
weight
parameter makes the second column and fourth row growable. This row
and column is occupied by the text widget, so all the extra space
is taken by it.
lbl = Label(self, text="Windows") lbl.grid(sticky=W, pady=4, padx=5)The label widget is created and put into the grid. If no column and row is specified, then the first column or row is assumed. The label sticks to the west and it has some padding around its borders.
area = Text(self)
area.grid(row=1, column=0, columnspan=2, rowspan=4,
padx=5, sticky=E+W+S+N)
The text widget is created and starts from the second row and first column. It
spans two columns and four rows. There is a 4 px space between the widget
and the left border of the root window. Finally, the widget sticks to all the four
sides. So when the window is resized, the text widget grows in all directions.
abtn = Button(self, text="Activate") abtn.grid(row=1, column=3) cbtn = Button(self, text="Close") cbtn.grid(row=2, column=3, pady=4)These two buttons go next to the text widget.
hbtn = Button(self, text="Help") hbtn.grid(row=5, column=0, padx=5) obtn = Button(self, text="OK") obtn.grid(row=5, column=3)These two buttons go below the text widget; the Help button takes the first column, the Ok Button takes the last column.
No hay comentarios:
Publicar un comentario