Search code examples
pythonpygobject

How to set a subset of widgets' colors in PyGObject 3.38?


I have 4 PyGObject applications I'm updating from older PyGObject versions to PyGObject 3.38.

Three of those applications went pretty smoothly. The fourth, hcm (https://stromberg.dnsalias.org/~strombrg/hcm/) is more troublesome. The application works, but I'm getting a DeprecationWarning I'd like to eliminate.

The warning looks like:

$ ./hcm.py --gui
./hcm.py:1035: DeprecationWarning: Gtk.Widget.modify_fg is deprecated
  gui_stuff.modify_fg(Gtk.StateType.NORMAL, Gdk.color_parse(color))

The code that is giving that warning currently looks like:

def color_traversal(gui_stuff, color):                                                                              
    """Traverse a widget hierarchy, changing colors as we go."""             
    # I'm thinking the stack requirements won't actually be that hefty, at least as
    # long as we're talking about a hierarchy and not a proper graph ^_^                     
    if hasattr(gui_stuff, 'get_children'):
        for child in gui_stuff.get_children():
            color_traversal(child, color)                                               
    if hasattr(gui_stuff, 'modify_fg'):                            
        # modify_fg is deprecated              
        gui_stuff.modify_fg(Gtk.StateType.NORMAL, Gdk.color_parse(color))
    # if hasattr(gui_stuff, 'override_color'):
        # override_color is deprecated too             
        # rgba = Gdk.RGBA()                              
        # rgba.parse(color)                                        
        # gui_stuff.override_color(Gtk.StateType.NORMAL, rgba)
    # if hasattr(gui_stuff, 'set_rgba'):     
        # This doesn't appear to work; none of the widgets I'm traversing have a set_rgba method
        # gdk_color = Gdk.color_parse(color)
        # rgba = Gdk.RGBA(gdk_color.red, gdk_color.green, gdk_color.blue, 1.0)
        # gui_stuff.set_rgba(rgba)
    # Maybe try get_style_context() ?
    # Maybe try CSS: https://shallowsky.com/blog/programming/styling-gtk3-with-css-python.html

"gui_stuff" is just a box or button or something. The color_traversal function just recursively traverses the widget and its component widgets changing their foreground color to something the caller specifies.

I have a lot of Python experience, but next to no CSS experience. Is CSS the only way of doing such things now? I must say, learning a new language to set the color of some widgets seems a bit much to ask compared to a function call.

Here's a quick picture of what I want it to look like: enter image description here

I've searched for how to do this for hours, but only found either deprecated functions or incomplete descriptions of CSS methods.

Thanks!


Solution

  • I changed to:

    for color in (b'darkblue', b'darkgreen', b'darkred'):
        provider = Gtk.CssProvider()                                      
        style_context = Gtk.StyleContext()
        style_context.add_provider_for_screen(       
            screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )                                          
        css = b'#%s { color: %s; }' % (color, color)                                
        provider.load_from_data(css)        
    

    And added a bunch of widget.set_name('darkgreen'), for example:

    self.stayopen_button.set_name(self.across_color)
    

    ...where self.across_color is just something like 'darkgreen'.

    And it's working. I guess the CSS wasn't that bad, but I still preferred just calling a method.