Search code examples
pythoncsspython-3.xgtkgtk3

Changing the color of Gtk.Entry text


I want to change the color of text in a Gtk.Entry. With override_color deprecated, this should be done using CSS, however I do not know how to apply it properly. Could someone help adapt the code below, such that the change_color function changes the color of text inside self.entry?

class Entry(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("destroy", Gtk.main_quit)

        self.entry = Gtk.Entry()

        self.button = Gtk.Button(label='button')
        self.button.connect('clicked', self.change_color)

        box = Gtk.Box()
        box.set_orientation(Gtk.Orientation.HORIZONTAL)
        box.add(self.entry)
        box.add(self.button)

        self.add(box)

    def change_color(self, widget):
        pass

window = Entry()
window.show_all()
Gtk.main()

Solution

  • Long time ago I also had the problem to understand CSS.

    It is little complicated to define CSS styles.

    screen = Gdk.Screen.get_default()
    provider = Gtk.CssProvider()
    
    style_context = Gtk.StyleContext()
    style_context.add_provider_for_screen(screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
    
    css = b"""
    #green-entry {color: red; background: #dfd} 
    #red-button {background: #fdd}
    """   # use prefix `b` or `.encode()` to create `bytes`
    
    provider.load_from_data(css)
    #provider.load_from_data("#green-entry {color: red; background: #dfd} #red-button {background: #fdd}".encode())
    #provider.load_from_path('app.css')
    

    But later you can assing style using CSS name

    self.entry.set_name('green-entry')
    
    self.button.set_name('red-button')
    

    Before:

    enter image description here

    After:

    enter image description here


    You can also assign colors to all widgets usings names like button, entry (without #)

    css = b"""
    entry {color: red; background: #dfd} 
    button {background: #fdd}
    """
    

    and they will be assigned at start and forever.

    But you can still use set_name() to assign some modifications.

    You can also use :hover to change color when mouse hover widget.

    css = b"""
    button       {background: #fdd}
    button:hover {background: #dfd}
    """
    

    Full working code:

    import gi
    gi.require_version("Gtk", "3.0")
    from gi.repository import Gtk
    from gi.repository import Gdk
    
    # --- CSS ---
    
    screen = Gdk.Screen.get_default()
    provider = Gtk.CssProvider()
    
    style_context = Gtk.StyleContext()
    style_context.add_provider_for_screen(screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
    
    css = b"""
    #green-entry {color: red; background: #dfd} 
    #red-button {background: #fdd}
    """   # use prefix `b` or `.encode()` to create `bytes`
    
    provider.load_from_data(css)
    #provider.load_from_data("#green-entry {color: red; background: #dfd} #red-button {background: #fdd}".encode())
    #provider.load_from_path('app.css')
    
    # ---
    
    class Entry(Gtk.Window):
        def __init__(self):
            Gtk.Window.__init__(self)
            self.connect("destroy", Gtk.main_quit)
    
            self.entry = Gtk.Entry(text='Hello World')
    
            self.button = Gtk.Button(label='button')
            self.button.connect('clicked', self.change_color)
    
            box = Gtk.Box()
            box.set_orientation(Gtk.Orientation.HORIZONTAL)
            box.add(self.entry)
            box.add(self.button)
    
            self.add(box)
    
            # --- assign ---
            
            #self.button.set_name('red-button')
            #self.entry.set_name('green-entry')
            
        def change_color(self, widget):
            self.button.set_name('red-button')
            self.entry.set_name('green-entry')
    
    window = Entry()
    window.show_all()
    Gtk.main()
    

    Resource: