Best Way to Set Entry Background Color in Python Gtk3 and Set Back to Default

Best way to set Entry Background Color in Python GTK3 and set back to default

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.


  1. 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); }')


  1. 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")

Change Background color of Gtk.Entry in Gtk3

You can use entry.override_background_color(Gtk.StateFlags.NORMAL, ...) (not override_bg()) or you can create some CSS:

provider = Gtk.CssProvider()
provider.load_from_data('.entry { background: red; }')
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

GTK3 reuse CSS state background colors

The color you're looking for is probably @base_color, for historical reasons. GTK has always had a distinction between "base" colors (for text entry widgets) and "background" colors (for everything else.)

It's not quite documentation, but examples are available on this page.

Python: Changing the select colour in a GtkTreeview

gtk_widget_modify_base has been deprecated since 3.0. You could have used gtk_widget_override_background_color, if it wasn't deprecated since 3.16. It's documentation states that:

If you wish to change the way a widget renders its background you should use a custom CSS style

However, if you want to disable selection color, the simpliest way is to unselect.

Your "changed" signal callback might look something like this:

def changed_cb(selection):
model, iter = get_selected (selection)
# if there is no selection, iter is None
if iter is None:
return
# do something useful
# now unselect
path = model.get_path(iter)
selection.unselect_path(path)
path.free() # not sure if python frees it automatically

Gtk3+ How to change Gtk.Entry border to a color?

Gtk+ 3.x uses CSS to style and theme the widgets. The CSS structure, style classes, did change from 3.0 up to 3.26. This means that it's important to know the version you are using.

With Gtk+ 3.22 you can use the css:

entry { 
border-color: Red;
}

With Gtk+ 3.18 use:

.entry {
border-color: Red;
}

Copy this css code to a file called test.css, then use this adapted example from the python gt3 tutorial:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GObject

class EntryWindow(Gtk.Window):

def __init__(self):
Gtk.Window.__init__(self, title="Entry Demo")
self.set_size_request(200, 100)

self.timeout_id = None

vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
self.add(vbox)

self.entry = Gtk.Entry()
self.entry.set_text("Hello World")
vbox.pack_start(self.entry, True, True, 0)

hbox = Gtk.Box(spacing=6)
vbox.pack_start(hbox, True, True, 0)

self.check_editable = Gtk.CheckButton("Editable")
self.check_editable.connect("toggled", self.on_editable_toggled)
self.check_editable.set_active(True)
hbox.pack_start(self.check_editable, True, True, 0)

self.check_visible = Gtk.CheckButton("Visible")
self.check_visible.connect("toggled", self.on_visible_toggled)
self.check_visible.set_active(True)
hbox.pack_start(self.check_visible, True, True, 0)

self.pulse = Gtk.CheckButton("Pulse")
self.pulse.connect("toggled", self.on_pulse_toggled)
self.pulse.set_active(False)
hbox.pack_start(self.pulse, True, True, 0)

self.icon = Gtk.CheckButton("Icon")
self.icon.connect("toggled", self.on_icon_toggled)
self.icon.set_active(False)
hbox.pack_start(self.icon, True, True, 0)

def on_editable_toggled(self, button):
value = button.get_active()
self.entry.set_editable(value)

def on_visible_toggled(self, button):
value = button.get_active()
self.entry.set_visibility(value)

def on_pulse_toggled(self, button):
if button.get_active():
self.entry.set_progress_pulse_step(0.2)
# Call self.do_pulse every 100 ms
self.timeout_id = GObject.timeout_add(100, self.do_pulse, None)
else:
# Don't call self.do_pulse anymore
GObject.source_remove(self.timeout_id)
self.timeout_id = None
self.entry.set_progress_pulse_step(0)

def do_pulse(self, user_data):
self.entry.progress_pulse()
return True

def on_icon_toggled(self, button):
if button.get_active():
icon_name = "system-search-symbolic"
else:
icon_name = None
self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,
icon_name)

win = EntryWindow()
style_provider = Gtk.CssProvider()
style_provider.load_from_path("test.css")

Gtk.StyleContext.add_provider_for_screen(
Gdk.Screen.get_default(),
style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

The result should be similar to this:

Sample Image

EDIT:

Result on Fedora 23 (Gtk+ 3.18.9):

Sample Image

How to set the background color in a Gtk3::TreeViewColumn?

The problem is this line:

my $column = Gtk3::TreeViewColumn->new_with_attributes
($c, $renderer, text => $n, background => $red);

Here, the background attribute expects a Gtk3::ListStore index, but you are not giving an integer index, rather you are supplying the RGBA object $red.

Here is an example of how you can do it by adding a dummy column to the Gtk::ListStore containing the color as a RGB string:

use feature qw(say);
use strict;
use warnings;
use Gtk3 -init;
use Glib 'TRUE', 'FALSE';

my @COLUMNS = qw( a b c );
my $ncols = scalar @COLUMNS;

my $red = "#f00";
my $window = Gtk3::Window->new ('toplevel');
my $notebook = Gtk3::Notebook->new;
$window->add($notebook);
my $sw = Gtk3::ScrolledWindow->new (undef, undef);
$notebook->append_page ($sw, Gtk3::Label->new ("tab"));

my $model = Gtk3::ListStore->new ((('Glib::String') x $ncols), 'Glib::String');
my $row = $model->append ();
$model->set ($row, (map {($_, $COLUMNS[$_])} 0..$#COLUMNS), $ncols, $red);
my $treeview = Gtk3::TreeView->new($model);
$sw->add($treeview);
while (my ($n, $c) = each @COLUMNS) {
my $renderer = Gtk3::CellRendererText->new;
my $column = Gtk3::TreeViewColumn->new_with_attributes
($c, $renderer, text => $n, background => $ncols);
$treeview->append_column($column);
}
$window->signal_connect( destroy => sub { Gtk3->main_quit() } );
$window->show_all;
Gtk3->main();

See also Python 3 and Gtk+3 - issue with TreeView and alternate colors of rows

How do I change a Gtk3 Entry text color in Python3?

Set the alpha channel to 1.0:

self.myOkEntry.override_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0.0, 1.0, 0.0, 1.0))

How to make buttons different colours in Python GTK3 (using gi)?

The preferred way in GTK3 is to use CSS for styling. Under Ubuntu 12.04 you may need to use background instead of background-color. But I don't know Python so I'll just give a link.

https://thegnomejournal.wordpress.com/2011/03/15/styling-gtk-with-css/



Related Topics



Leave a reply



Submit