color propagation in tkinter

John Posner jjposner at snet.net
Thu Apr 23 02:30:42 CEST 2009


Alan G Isaac wrote:
> Yes, that's what I am currently doing.
> But it seems that that is exactly the kind of thing
> we are enabled to avoid with e.g., named fonts.
> So I was hoping for an equivalent functionality
> for colors.  From your answer, I am guessing there
> is none.
Not sure this would help, but Tkinter supports the X Window System 
"resources" facility, calling it the "option database". [1]  So it's 
pretty easy to create a subclass of Tkinter.Frame whose instances get a 
user-configured background color, e.g. cyan:

  class Aframe(Frame):
      def __init__(self, master, **kwargs):
          Frame.__init__(self, master, class_="Aframe", **kwargs)
 ...
  root.option_add("*Aframe*background", "cyan")

Notes:

* The class name "Aframe" in the option_add() statement does not refer 
to the Python subclass "Aframe". Rather, it refers to the value of 
"class_=" in the __init__() method.

* The "class_=" keyword argument must appear in the call to the parent 
class's __init__() method. You can't reconfigure an existing object, 
e.g.: myobj.config(class_="Aframe").

* As far as I can tell, the "class_=" keyword argument is supported only 
by the Frame widget initializer. You cannot, for example, use this 
facility to specify the background color of a Tkinter.Label subclass. :=(

* This facility initializes a new widget, but cannot be used to 
reconfigure an existing widget. [2]

Sounds useful, huh?  :-) Anyway, here's a proof-of-concept:

from Tkinter import *

class Aframe(Frame):
    def __init__(self, master, **kwargs):
        Frame.__init__(self, master, class_="Aframe", **kwargs)

class Bframe(Frame):
    def __init__(self, master, **kwargs):
        Frame.__init__(self, master, class_="Bframe", **kwargs)

root = Tk()
root.geometry("200x300")

# set backgrounds for different classes
root.option_add("*Aframe*background", "cyan")
root.option_add("*Bframe*background", "pink")

# overall frame
panel = Frame(root)
panel.pack(padx=25, pady=20, expand=YES, fill=BOTH)

# vertical padding factor
p = 10

# created colored frames
Aframe(panel).pack(pady=p, expand=YES, fill=BOTH)
Bframe(panel).pack(pady=p, expand=YES, fill=BOTH)
Aframe(panel).pack(pady=p, expand=YES, fill=BOTH)
Aframe(panel).pack(pady=p, expand=YES, fill=BOTH)
Aframe(panel).pack(pady=p, expand=YES, fill=BOTH)
Bframe(panel, relief=GROOVE, bd=4).pack(pady=p, expand=YES, fill=BOTH)

# go
root.mainloop()

>
> This is an example where different behavior by
> StringVar could have been put to good use, I think.
I don't follow this. Would you elaborate?


[1] http://infohost.nmt.edu/tcc/help/pubs/tkinter/option-database.html
[2] http://www.cs.man.ac.uk/~fellowsd/tcl/option-tutorial.html says 
"Note that there is no automatic update of existing widgets when the 
database is modified. If you want this, you will need to implement it 
yourself."




More information about the Python-list mailing list