Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #80975 > unrolled thread

I dont understand root['bg'] = 'red' where root is a tkinter.Tk object

Started by"ast" <nomail@invalid.com>
First post2014-11-17 14:32 +0100
Last post2014-11-17 14:48 -0500
Articles 4 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  I dont understand root['bg'] = 'red' where root is a tkinter.Tk object "ast" <nomail@invalid.com> - 2014-11-17 14:32 +0100
    Re: I dont understand root['bg'] = 'red' where root is a tkinter.Tk object Peter Otten <__peter__@web.de> - 2014-11-17 15:14 +0100
      Re: I dont understand root['bg'] = 'red' where root is a tkinter.Tk object "ast" <nomail@invalid.com> - 2014-11-17 17:01 +0100
    Re: I dont understand root['bg'] = 'red' where root is a tkinter.Tk object Terry Reedy <tjreedy@udel.edu> - 2014-11-17 14:48 -0500

#80975 — I dont understand root['bg'] = 'red' where root is a tkinter.Tk object

From"ast" <nomail@invalid.com>
Date2014-11-17 14:32 +0100
SubjectI dont understand root['bg'] = 'red' where root is a tkinter.Tk object
Message-ID<5469f8d3$0$5132$426a74cc@news.free.fr>
Hello,

import tkinter
root = tkinter.Tk()

Let's see all attributes of root:

>>> root.__dict__
{'master': None, 'children': {}, '_tclCommands': ['tkerror', 'exit', '13825848destroy'], 'tk': 
<tkapp object at 0x02949C28>, '_tkloaded': 1}

Now we change the background color using following command:
>>> root['bg'] = 'red'

I am wondering what 'bg' is for object root. Is it an attribute ?

>>> root.__dict__
{'master': None, 'children': {}, '_tclCommands': ['tkerror', 'exit', '13825848destroy'], 'tk': 
<tkapp object at 0x02949C28>, '_tkloaded': 1}

No, 'bg' is not in root attribute's list. So what is it ?

Thx

[toc] | [next] | [standalone]


#80976

FromPeter Otten <__peter__@web.de>
Date2014-11-17 15:14 +0100
Message-ID<mailman.15958.1416233676.18130.python-list@python.org>
In reply to#80975
ast wrote:

> Hello,
> 
> import tkinter
> root = tkinter.Tk()
> 
> Let's see all attributes of root:
> 
>>>> root.__dict__
> {'master': None, 'children': {}, '_tclCommands': ['tkerror', 'exit',
> {'13825848destroy'], 'tk':
> <tkapp object at 0x02949C28>, '_tkloaded': 1}
> 
> Now we change the background color using following command:
>>>> root['bg'] = 'red'
> 
> I am wondering what 'bg' is for object root. Is it an attribute ?
> 
>>>> root.__dict__
> {'master': None, 'children': {}, '_tclCommands': ['tkerror', 'exit',
> {'13825848destroy'], 'tk':
> <tkapp object at 0x02949C28>, '_tkloaded': 1}
> 
> No, 'bg' is not in root attribute's list. So what is it ?

Let's drill down a bit:


>>> import tkinter, inspect
>>> print(inspect.getsource(tkinter.Tk.__setitem__))
    def __setitem__(self, key, value):
        self.configure({key: value})

>>> print(inspect.getsource(tkinter.Tk.configure))           
    def configure(self, cnf=None, **kw):
        """Configure resources of a widget.

        The values for resources are specified as keyword
        arguments. To get an overview about
        the allowed keyword arguments call the method keys.
        """
        return self._configure('configure', cnf, kw)

>>> print(inspect.getsource(tkinter.Tk._configure))
    def _configure(self, cmd, cnf, kw):
        """Internal function."""
        if kw:
            cnf = _cnfmerge((cnf, kw))
        elif cnf:
            cnf = _cnfmerge(cnf)
        if cnf is None:
            return self._getconfigure(_flatten((self._w, cmd)))
        if isinstance(cnf, str):
            return self._getconfigure1(_flatten((self._w, cmd, '-'+cnf)))
        self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))

>>> print(inspect.getsource(root.tk.call))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/inspect.py", line 830, in getsource
    lines, lnum = getsourcelines(object)
  File "/usr/lib/python3.4/inspect.py", line 819, in getsourcelines
    lines, lnum = findsource(object)
  File "/usr/lib/python3.4/inspect.py", line 655, in findsource
    file = getfile(object)
  File "/usr/lib/python3.4/inspect.py", line 536, in getfile
    'function, traceback, frame, or code object'.format(object))
TypeError: <built-in method call of tkapp object at 0x7f84ec9f3370> is not a 
module, class, method, function, traceback, frame, or code object

OK, we've reached C code, from here more traditional methods of code 
inspection are required.

tkinter is a wrapper for a GUI written in tcl/tk. For every GUI element in 
tkinter there is a corresponding tcl object that holds the actual bg data. 
It's just that at some point in the development of tkinter someone thought 
that

widget["bg"] = "red"

is more convenient than

widget.configure(bg="red")

While it would have been possible to choose

widget.bg = "red"

that would have mixed the tcl and python namespaces. When the tcl object 
acquires new attributes hilarity ensues...

(I probably would have chosen widget.gui.bg = "red")

[toc] | [prev] | [next] | [standalone]


#80978

From"ast" <nomail@invalid.com>
Date2014-11-17 17:01 +0100
Message-ID<546a1bcd$0$2308$426a74cc@news.free.fr>
In reply to#80976
"Peter Otten" <__peter__@web.de> a écrit dans le message de 
news:mailman.15958.1416233676.18130.python-list@python.org...

ty 

[toc] | [prev] | [next] | [standalone]


#80980

FromTerry Reedy <tjreedy@udel.edu>
Date2014-11-17 14:48 -0500
Message-ID<mailman.15961.1416253764.18130.python-list@python.org>
In reply to#80975
On 11/17/2014 8:32 AM, ast wrote:
> Hello,
>
> import tkinter
> root = tkinter.Tk()
>
> Let's see all attributes of root:
>
>>>> root.__dict__
> {'master': None, 'children': {}, '_tclCommands': ['tkerror', 'exit',
> '13825848destroy'], 'tk': <tkapp object at 0x02949C28>, '_tkloaded': 1}
>
> Now we change the background color using following command:

As Peter Otten nicely explained, tkinter widgets are proxies for tk 
widgets, with a few extra attributes added (as shown above).  Tk widget 
methods are proxied as tkinter widget methods, with Python syntax and 
objects.

Tk widgets each *have* an internal options dictionary, created with the 
widget and later accessed trough the .configure method.  As tcl 
dictionaries, keys and values are strings. The configure method with no 
args returns the entire options dictionary and the Python wrapper return 
it as a Python dict.  Each value is a 2- or 5-tuple.

 >>> root.configure()
{'takefocus': ('takefocus', 'takeFocus', 'TakeFocus', '0', '0'), 'pady': 
('pady', 'padY', 'Pad', <pixel object: '0'>, <pixel object: '0'>), 
'relief': ('relief', 'relief', 'Relief', <index object: 'flat'>, 
'flat'), 'bg': ('bg', '-background'), 'class': ('class', 'class', 
'Class', 'Toplevel', 'Tk'), 'visual': ('visual', 'visual', 'Visual', '', 
''), 'highlightthickness': ('highlightthickness', 'highlightThickness', 
'HighlightThickness', <pixel object: '0'>, 0), 'borderwidth': 
('borderwidth', 'borderWidth', 'BorderWidth', <pixel object: '0'>, 0), 
'highlightbackground': ('highlightbackground', 'highlightBackground', 
'HighlightBackground', <color object: 'SystemButtonFace'>, 
'SystemButtonFace'), 'width': ('width', 'width', 'Width', <pixel object: 
'0'>, 0), 'container': ('container', 'container', 'Container', 0, 0), 
'bd': ('bd', '-borderwidth'), 'background': ('background', 'background', 
'Background', <border object: 'SystemButtonFace'>, 'SystemButtonFace'), 
'cursor': ('cursor', 'cursor', 'Cursor', '', ''), 'highlightcolor': 
('highlightcolor', 'highlightColor', 'HighlightColor', <color object: 
'SystemWindowFrame'>, 'SystemWindowFrame'), 'use': ('use', 'use', 'Use', 
'', ''), 'colormap': ('colormap', 'colormap', 'Colormap', '', ''), 
'height': ('height', 'height', 'Height', <pixel object: '0'>, 0), 
'padx': ('padx', 'padX', 'Pad', <pixel object: '0'>, <pixel object: 
'0'>), 'menu': ('menu', 'menu', 'Menu', '', ''), 'screen': ('screen', 
'screen', 'Screen', '', '')}

Once created, this Python snapshot is independent of the tk options 
dictionary.  Changes in either do not affect the other.

Since sometime in 2.x, each tkinter widget *also* acts as a partial 
proxy for the tk widget's option dict.  Getting and setting a value by 
key works.

 >>> root['bg']
'SystemButtonFace'

>>>> root['bg'] = 'red'

(Interior of root window turn bright red.)
 >>> root['bg']
'red'

The keys method works. (I did not notice until reading the source in 
Peter's reply.)

 >>> root.keys()
['bd', 'borderwidth', 'class', 'menu', 'relief', 'screen', 'use', 
'background', 'bg', 'colormap', 'container', 'cursor', 'height', 
'highlightbackground', 'highlightcolor', 'highlightthickness', 'padx', 
'pady', 'takefocus', 'visual', 'width']

Other dict methods, such as .items(), do not, instead raising 
AttributeError.  But items can be simulated.

 >>> for k in sorted(root.keys()):
	print(k, root[k])
	
background red
bd 0
bg red
borderwidth 0
class Tk
colormap
container 0
cursor
height 0
highlightbackground SystemButtonFace
highlightcolor SystemWindowFrame
highlightthickness 0
menu
padx 0
pady 0
relief flat
screen
takefocus 0
use
visual
width 0

> I am wondering what 'bg' is for object root. Is it an attribute ?

No.  It is a key of one of the key,value pairs in the dict that root 
acts like.  This is the same as for any dict.  The attribute namespace 
of the dict (implemented by .__dict__) is separate from the namespace 
that the dict itself implements.  Given d = {1:'one'}, 1 is not an 
attribute of d.

-- 
Terry Jan Reedy

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web