What is the best way to set background color for one entry and set it back to the default color?
My script is now working but I am very sure this is not the best way.
Also I still have two problems:
self.entry_default_background_color_str
into the CSS text. import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
class Window(Gtk.Window):
def __init__(self):
self.screen = Gdk.Screen.get_default()
self.gtk_provider = Gtk.CssProvider()
self.gtk_context = Gtk.StyleContext()
self.gtk_context.add_provider_for_screen(self.screen, self.gtk_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
Gtk.Window.__init__(self, title="Check Input")
self.set_size_request(300, 80)
self.mainbox = Gtk.VBox()
self.add(self.mainbox)
# entry
self.name_entry = Gtk.Entry()
self.name_entry.set_name("name_entry")
self.mainbox.pack_start(self.name_entry, True, True, 0)
self.name_entry.connect("changed", self.check_input)
entry_context = self.name_entry.get_style_context()
self.entry_default_background_color = entry_context.get_background_color(Gtk.StateType.NORMAL)
self.entry_default_background_color_str = self.entry_default_background_color.to_string()
self.show_all()
def check_input(self, _widget=None):
if "red" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background: red; }')
elif "green" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background: green; }')
else:
self.gtk_provider.load_from_data('#name_entry { background: ' + self.entry_default_background_color_str + '; }')
def main():
window = Window()
Gtk.main()
if __name__ == "__main__":
main()
Right-click the upper-left corner of the Python console window and select Properties. In the dialog box that appears, pick the tab labeled Colors. On it you can set the screen background and text color.
I will first address the issues you mention, as they give insight into what is going on in GTK and OP's code. The answer to the main question (and proper code for doing this) is all the way at the bottom of the answer.
- If I insert a text, not containing string "red" or "green" and select this text I cant see my selection because It is all white.
The reason this happens is because the background
property is used, this sets all background related properties of the Entry to that color. So both that of the selection as well as the "real" background.
Then the question is what property do we use, this is a part of GTK which is poorly documented but we can find out using the GtkInspector which lets us see what style properties are changing. This yields we should use background-image
instead and that background-color
is used for the background of the selection.
Just setting the background-image
to the color doesn't work, that gives a error because a image is expected. So now we have to figure out a way to make our color
into something we can set as a background-image
luckily the inspector shows us the way GTK does it internally namely by wrapping the color like this: linear-gradient(red)
. Doing so creates a uniform red image which can be used as the background.
Applying this knowledge to your code gives us:
if "red" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background-image: linear-gradient(red); }')
elif "green" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background-image: linear-gradient(green); }')
- I think there are better ways then the way I insert
self.entry_default_background_color_str
into the CSS text.
There is indeed a better way, namely don't do it. We can easily return to the default by just feeding the CssProvider
an empty version of the css, this will overwrite the old one and thus remove any old style properties like for example the color.
Combining this with the previous section gives us:
if "red" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background-image: linear-gradient(red); }')
elif "green" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background-image: linear-gradient(green); }')
else:
self.gtk_provider.load_from_data('#name_entry {}')
What is the best way to set background color for one entry and set it back to the default color?
Now that I addressed the issues with your code, now this all important question. The way your are doing it now is replacing the CSS file, which works fine but in the long run is really inefficient. Normally you would load the CSS and uses classes and ids to tell it which styling to apply.
Below I adapted your code to do it this way, check the comments for the explanation.
def __init__(self):
screen = Gdk.Screen.get_default()
gtk_provider = Gtk.CssProvider()
gtk_context = Gtk.StyleContext()
gtk_context.add_provider_for_screen(screen, gtk_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
# Create the window
Gtk.Window.__init__(self, title="Check Input")
self.set_size_request(300, 80)
self.mainbox = Gtk.VBox()
self.add(self.mainbox)
# Load the CSS
gtk_provider.load_from_data("""
#name_entry.red { background-image: linear-gradient(red); }
#name_entry.green { background-image: linear-gradient(green); }
""")
# Create the entry and give it a name which will be the ID
name_entry = Gtk.Entry()
name_entry.set_name("name_entry")
self.mainbox.pack_start(name_entry, True, True, 0)
# Add the listener
name_entry.connect("changed", self.check_input)
self.show_all()
def check_input(self, entry):
# Get the style context for this widget
entry_style_context = entry.get_style_context()
# Check if our text contains red
if "red" in entry.get_text():
# Add the red class, so now the styling with .red is applied
entry_style_context.add_class("red")
# Check if our text contains green
elif "green" in entry.get_text():
# Add the red class, so now the styling with .green is applied
entry_style_context.add_class("green")
else:
# When the text doesn't contain it remove the color classes to show the default behaviour
entry_style_context.remove_class("red")
entry_style_context.remove_class("green")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With