А если с Tkinter'ом использовать надстройку над диспетчером pack (вроде это декоратором называется) с которой тот заставляет курить в сторонке и grid и place - векторы, то вообще всё весело будет.
Векторы (модифицирована под себя, оригинал искать по имени tVector)
"""
Convenience layer for Tkinter.
Allows window specifications to be created with far less,
and much more readable code, than doing it by hand.
Contains classes Row and Col, for building rows and columns
of widgets, and building these into a live frame.
Example:
from Tkinter import *
from Vector import *
class mywin:
def __init__(self, parent):
self.layout = Col(W(Label, 'L1',
text="Window Heading",
font="helvetica 16 bold"),
W(Checkbutton, 'Chk1',
text="A checkbutton"),
Row(W(Button, 'but1',
text="Button 1",
command=self.on_button1),
W(Button, 'but2',
text="Button 2",
command=self.on_button2),
W(Button, 'but3',
text="Button 3",
command=self.on_button3)),
Row(W(Entry, 'fld1',
text="field 1"),
W(Entry, 'fld2',
text="field 2")))
self.layout.build(parent)
def on_button1(self):
print "clicked button1"
self.layout.wid('but1', text="New Button1 label")
def on_button2(self):
print "clicked button2"
self.layout.wid('but1', text='Button 1')
def on_button3(self):
print "clicked button3"
def mainloop(self):
self.layout.mainloop()
root = Tk()
app = mywin(root)
app.mainloop()
"""
import Tkinter
from Tkinter import *
class Vector(Frame):
"""
Tkinter vectors.
A helper class for the easy creation and use of Tkinter layouts.
(don't use this class directly - you should use the derived 'Row'
and 'tVer' classes instead)
For a working example, see this module's docstring
"""
def __init__(self, direction, *widgets, **kwds):
"""
Creates an array of widgets (or widget vectors)
Best not to use this class directly - use one of the derived
classes 'HOR' or 'VER' instead.
"""
if direction == 'right':
self.packside = LEFT
else:
self.packside = TOP
if kwds.has_key('widget_list'):
self.widlist = kwds['widget_list']
del kwds['widget_list']
else:
self.widlist = widgets
self.kwds = kwds
self.wids = {} # populate this during build
def build(self, parent, **kw):
"""
Recursively descend through the widgets list, and construct/pack
the window structure
"""
self.wids = {}
if kw.has_key('fill'):
fill = kw['fill']
del kw['fill']
else:
fill = BOTH
if kw.has_key('expand'):
expand = kw['expand']
del kw['expand']
else:
expand = YES
# construct Frame for this vector
#Frame.__init__(self, parent, self.kwds)
Frame.__init__(self, parent, self.kwds)
self.pack(side=self.packside, fill=fill, expand=expand)
for wid in self.widlist:
if isinstance(wid, Vector):
wname = None
wref = wid.build(self)
self.wids.update(wid.wids)
else:
wcls = wid['class']
wname = wid['name']
wargs = wid['args']
wkwds = wid['kwds']
if wkwds.has_key('fill'):
fill = wkwds['fill']
del wkwds['fill']
else:
fill = BOTH
if wkwds.has_key('expand'):
expand = wkwds['expand']
del wkwds['expand']
else:
expand = YES
wref = wcls(self, *wargs, **wkwds)
wref.pack(side=self.packside, fill=fill, expand=expand)
if wname:
self.wids[wname] = wref
return self
def control(self, widname=None, **kwds):
"""
Versatile method.
Looks up component widgets by name. If any keywords are supplied,
the widget's config() method will be called with these keywords.
3 ways of using:
- with no arguments at all, returns a list of widget names
- with just a widget name argument, returns a ref to that widget
- with widget name and some keywords, calls config() on that widget
and passes the given keywords.
Examples:
# get a list of widgets for vector 'mywin'
widgets = mywin.wid()
# get a handle to the widget 'label1'
mylabel = mywin.wid('label1')
# change the text of 'label1'
mywin.wid('label1', text="Different text for label1")
"""
if not widname:
return self.wids.keys()
else:
wid = self.wids[widname]
if len(kwds) > 0:
wid.config(**kwds)
else:
return self.wids[widname]
class Row(Vector):
"""
Creates a horizontal vector of widgets.
For usage info, refer to Vector docstring
"""
def __init__(self, *widgets, **kwds):
"""
Constructor for Row - a horizontal vector of widgets
Arguments:
- widget1
- widget2
- ...
Each widget should be either be something returned from W,
or a Row or Col instance.
For an example, refer to docstring for Vector class
"""
Vector.__init__(self, 'right', *widgets, **kwds)
class Col(Vector):
"""
Creates a vertical column of widgets.
For usage info, refer to Vector docstring
"""
def __init__(self, *widgets, **kwds):
"""
Constructor for Row - a vertical vector of widgets
Arguments:
- widget1
- widget2
- ...
Each widget should be either be something returned from W,
or a Row or Col instance.
For an example, refer to docstring for Vector class
"""
Vector.__init__(self, 'down', *widgets, **kwds)
def W(widclass, widname, *args, **kwds):
"""
Helper function for Row and Col classes.
Generates a widget entry and translates it into a dict that can be
fed straight to the Row and Col constructors.
Refer to the Vector docstring for more info.
Arguments:
- widclass - a widget class object that behaves like normal tk widgets
- widname - name to give to this widget (accessible later via
Row.wid and Col.wid methods)
- extra arguments are passed to the widget constructor
Keywords:
- anything you give gets passed straight to widget constructor
Example:
W(Tkinter.Button, 'mybutton1', text="Button 1")
"""
return {'name':widname,
'class':widclass,
'args':args,
'kwds':kwds}
Пример:
lab_1_1 = tk.Frame()
#Задаём расположение и параметры виджетов
#Формат - W(класс_виджета,идентификатор,параметры конфигурации)
#Row( W(), ... ) - виджеты будут сформированы в строку
#Col - в столбец
layout = [W(tk.Label,'caesar_title',text='Шифр Цезаря',font=("Monotype Corsiva", 17, "bold italic")),
W(tk.Entry,'caesar_entry'),
W(tk.Button,'caesar_button',text = 'Зашифровать',height=3,width=10,expand=tk.NO,fill=tk.NONE,command=lambda: caesar_proxy(root,caesar)),
W(MultiListbox,'caesar_list',(('Ключ', 10), ('Зашифрованная строка', 40)))]
caesar = Col(widget_list = layout)
caesar.build(lab_1_1)
caesar.control('caesar_entry').insert(0,"quick brown fox jumps over lazy dog")