Welcome, guest | Sign In | My Account | Store | Cart

A common way to create new compound widgets is to inherit Frame, create everything you need inside it and pack this base Frame on your application. Here's an alternative to this method, that sets geometry methods and options from a wiget to another...

Python, 74 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# file: LabeledEntry.py
# A simple example of moving options and
# geometry methods from a widget to another
# Pedro Werneck <pedro.werneck@bol.com.br>

from Tkinter import *


class LabeledEntry(Entry):
    """
    An Entry widget with an attached Label
    """
    def __init__(self, master=None, **kw):
        """
        Valid resource names: background, bd, bg, borderwidth, cursor,
        exportselection, fg, font, foreground, highlightbackground,
        highlightcolor, highlightthickness, insertbackground,
        insertborderwidth, insertofftime, insertontime, insertwidth,
        invalidcommand, invcmd, justify, relief, selectbackground,
        selectborderwidth, selectforeground, show, state, takefocus,
        textvariable, validate, validatecommand, vcmd, width,
        xscrollcommand.
        
        The following options apply to the Label: text, textvariable,
        anchor, bitmap, image
        
        The following options apply to the Geometry manager: padx, pady,
        fill, side
        """
        fkw = {}                                       # Frame options dictionary
        lkw = {'name':'label'}                         # Label options dictionary
        skw = {'padx':0, 'pady':0, 'fill':'x',         # Geometry manager options dictionary
                'side':'left'}
        fmove = ('name',)                               # Options to move to the Frame dictionary
        lmove = ('text', 'textvariable',
                 'anchor','bitmap', 'image')            # Options to move to the Label dictionary
        smove = ('side', 'padx', 'pady','side')         # Options to move to the Geometry manager dictionary

        for k in kw.keys():
            if type(k) == ClassType or k in fmove:
                fkw[k] = kw[k]
                del kw[k]
            elif k in lmove:
                lkw[k] = kw[k]
                del kw[k]
            elif k in smove:
                skw[k] = kw[k]
                del kw[k]

        self.body = apply(Frame, (master, ), fkw)
        self.label = apply(Label, (self.body,), lkw)
        self.label.pack(side='left', fill=skw['fill'], padx=skw['padx'], pady=skw['pady'])
        apply(Entry.__init__, (self, self.body), kw)
        self.pack(side=skw['side'], fill=skw['fill'], padx=skw['padx'], pady=skw['pady'])


        methods = (Pack.__dict__.keys() +              # Set Frame geometry methods to self.
                   Grid.__dict__.keys() +
                   Place.__dict__.keys())              
        for m in methods:
            if m[0] != '_' and m != 'config' and m != 'configure':
                setattr(self, m, getattr(self.body, m))       


if __name__ == '__main__':
    root = Tk()
    le1 = LabeledEntry(root, name='label1', text='Label 1: ', width=5, relief=SUNKEN, bg='white', padx=3)
    le2 = LabeledEntry(root, name='label2', text='Label 2: ', relief=SUNKEN, bg='red', padx=3)
    le3 = LabeledEntry(root, name='label3', text='Label 3: ', width=40, relief=SUNKEN, bg='yellow', padx=3)

    le1.pack(expand=1, fill=X)
    le2.pack(expand=1, fill=X)
    le3.pack(expand=1, fill=X)
    root.mainloop()

The usual approach to inherit Frame and pack your slave widgets inside it has a few problems... you need to create aditional methods or options to access these slaves attributes inside the class, or do it by it's reference...

Here, I present an idea I saw on the ScrolledText widget, but can be expanded to any amount of slaves. Instead of inheriting Frame, you inherit your main widget, create a Frame widget, to use as body like the usual way, create dicts for each slave inside and move the respective options to them. Than, after packing the main widget, you can reset it's geometry methods to the base Frame attributes, so acessing the object methods will instead access the inner base Frame geometry methods.

The advantages of this approach is that you can create your widget, with options to all slave widgets inside it in a single line, just like any other widget, instead of doing further w.configure or w['option'] calls to set it exactly like you want... the disavantage is that is dificult to handle options with the same name on different slave widgets

Created by Pedro Werneck on Sat, 24 May 2003 (PSF)
Python recipes (4591)
Pedro Werneck's recipes (1)

Required Modules

Other Information and Tasks