Ask for help about a tkinter problem

Peter Otten __peter__ at web.de
Sun Aug 20 05:51:40 EDT 2017


jfong at ms4.hinet.net wrote:

> I am running a tkinter tutor downloaded from web,
> https://github.com/daleathan/widget-tour-py3. there are two files
> involved:
> 
> --------------------
> #file button.py
> 
> from tkinter import *
> from tkinter.ttk import *
> import infrastructure
> ...
> class ButtonsDemoWindow( infrastructure.DemoWindow ):
>     ...
>     def __init__( self ):
>         ...
>         ...
>         for c in ('Peach Puff', 'Light Blue', 'Sea Green', 'Yellow' ):
>             b = Button(self.frame, text=c)
>             b['command'] = infrastructure.callit( self.callback, c )
>             b.pack( side=TOP, expand=YES, pady=2 )
> 
>     def callback(self, color):
>         self.frame['background']=color
> 
> def runDemo():
>     ButtonsDemoWindow()
> 
> ----------------------
> #file infrastructure.py
> ...
> class DemoWindow( Toplevel ):
>     ...
>     ...
> class callit:
>     def __init__(self, function, *args ):
>         self.f = function
>         self.args = args
> 
>     def __call__(self, *ignored):
>         self.f( *self.args)
> 
> --------------------
> I run it under the DOS box:
> 
>     D:\Works\Python\widget-tour-py3-master>python
>     Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600
>     32 bit (Intel)] on win32 Type "help", "copyright", "credits" or
>     "license" for more information.
>     >>> import button
>     >>> button.runDemo()
> 
> after the window shows up, I pressed one of the buttons and get the error
> below:
> 
>>>> Exception in Tkinter callback
> Traceback (most recent call last):
>   File "C:\Python34\lib\tkinter\__init__.py", line 1538, in __call__
>     return self.func(*args)
>   File "D:\Works\Python\widget-tour-py3-master\infrastructure.py", line
>   216, in __call__
>     self.f( *self.args)
>   File "D:\Works\Python\widget-tour-py3-master\button.py", line 39, in
>   callback
>     self.frame['background']=color
>   File "C:\Python34\lib\tkinter\__init__.py", line 1331, in __setitem__
>     self.configure({key: value})
>   File "C:\Python34\lib\tkinter\__init__.py", line 1324, in configure
>     return self._configure('configure', cnf, kw)
>   File "C:\Python34\lib\tkinter\__init__.py", line 1315, in _configure
>     self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
> _tkinter.TclError: unknown option "-background"
> 
> 
> When I looked into the file tkinter\__init__.py, I found there is codes
> which add conditionally a '-' onto the original cnf argument:

That is just a peculiarity of TCL; a "-" is added to the option by the 
Python wrapper before passing it along
 
> 1305  def _configure(self, cmd, cnf, kw):
> 1306      """Internal function."""
> ...
> ...
> 1313      if isinstance(cnf, str):
> 1314          return self._getconfigure1(_flatten((self._w, cmd,
> '-'+cnf)))
> 
> Is it the reason this exception raised? Why is that?

I can confirm the problem. It looks like the bug was introduced when the 
example was converted from stock tkinter to the new ttk widget set.

While

frame["background"] = color

works when frame is a tkinter.Frame widget the newer tkinter.ttk.Frame 
widget uses "styles" to configure its appearance. 

I have not used that new feature, but with the help of

http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/ttk-style-layer.html

and some trial and error I modified the example to use a style:

$ diff -u button.py button_fixed.py 
--- button.py   2017-08-20 11:44:33.841839812 +0200
+++ button_fixed.py     2017-08-20 11:44:04.032426163 +0200
@@ -25,7 +25,9 @@
         
         infrastructure.DemoWindow.__init__(self, intro, 'button.py' )
 
-        self.frame=Frame(self)
+        self.style = Style(self)
+        self.frame=Frame(self, style="foo.TFrame")
+
         self.frame.pack(expand=YES, fill=BOTH )
         for c in ('Peach Puff', 'Light Blue',
                   'Sea Green', 'Yellow' ):
@@ -36,7 +38,7 @@
             
 
     def callback(self, color):
-        self.frame['background']=color
+        self.style.configure("foo.TFrame", background=color)
             
 
 def runDemo():
$ 

However, I'm not sure if this is the canonical way to write it...




More information about the Python-list mailing list