I have a tray icon with a popup menu. I am trying to set the background color of the menu items in this popup. I am able to set the text color but not the background color of the menu item.
The background that appears is the default Ubuntu orange, and I can't override it.
I've created a sample application that demonstrates this problem. Just copy-paste it into a .py file and it should run.
from gi.repository import Gtk, Gdk
import sys
class TrayIcon:
def __init__(self):
self.statusicon = Gtk.StatusIcon()
self.statusicon.set_from_stock(Gtk.STOCK_MEDIA_PLAY)
self.statusicon.connect("popup-menu", self.OnShowPopupMenu)
window = Gtk.Window()
def OnShowPopupMenu(self, icon, button, time):
menu = Gtk.Menu()
first = self.GetMenuItem("First")
second = self.GetMenuItem("Second")
menu.append(first)
menu.append(second)
menu.show_all()
menu.popup(None, None, lambda w,x: self.statusicon.position_menu(menu, self.statusicon), self.statusicon, 3, time)
def GetMenuItem(self, txt):
menuItem = Gtk.MenuItem(txt)
screen = Gdk.Screen.get_default()
css_provider = Gtk.CssProvider()
#css_provider.load_from_data("GtkWidget { color:white; background-color: green; } GtkWidget:hover,GtkWidget:selected { color:white; background-color:pink;}")
css_provider.load_from_data("GtkMenuItem { color:#0f0; background-color: #f00; } GtkMenuItem:hover,GtkMenuItem:selected { color:#00f; background-color:#f00; font-weight:bold;}")
context = Gtk.StyleContext()
context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
menuItem.connect("button_press_event", self.exit)
return menuItem
def exit(self, a,b):
sys.exit()
TrayIcon()
Gtk.main()
For GtkMenuItem the normal background and :hover background are being ignored. For GtkWidget the :hover background is being ignored. My aim is to prevent that Ubuntu orange from showing up without disabling the menu item.
Is there a way to set the background and hover/mouseover color of a GtkMenuItem? (without using 'import gtk')
I am using Ubuntu 12.04, default theme.
Edit1: To add a bit of clarity, this is what I am trying to do, but without 'import gtk'.
#Prevent background color when mouse hovers
style = menuItem.get_style().copy()
style.bg[gtk.STATE_SELECTED] = style.bg[gtk.STATE_NORMAL]
menuItem.set_style(style)
Edit2: I've also tried override_background_color() and modify_bg, and again, the orange still shows up on hover. Here are variants of what I have tried.
menuItem.override_background_color(Gtk.StateFlags.NORMAL,Gdk.RGBA(1.0,0.0,0.0,1))
menuItem.modify_bg(Gtk.StateFlags.NORMAL,Gdk.color_parse("red"))
menuItem.override_background_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(1.0, 1.0, 1.0, 1.0))
menuItem.override_background_color(Gtk.StateFlags.SELECTED, Gdk.RGBA(1.0, 1.0, 1.0, 1.0))
menuItem.override_background_color(Gtk.StateFlags.FOCUSED, Gdk.RGBA(1.0, 1.0, 1.0, 1.0))
Edit3: Answer has been provided, see this post.
After a lot of digging, the answer turned out to be somewhat obscure.
background-color
does not work. I had to use background
-unico-inner-stroke-width
I ended up at a GTK3 CSS file for the Ubuntu theme itself to see what was happening, located here:
/usr/share/themes/Ambiance/gtk-3.0/gtk-widgets.css
I got the -unico-inner-stroke-width
property from the CSS file above. I cannot determine why background-color
in my script is being ignored, but it is, at least on Ubuntu 12.04.
I was also forced to 're-set' the background and border colors of the elements I was changing as they would otherwise appear strange. This is the minimum CSS I had to use
GtkMenuItem
{
border:@bg_color;
background:@bg_color;
}
GtkMenuItem:hover
{
background:@selected_bg_color;
}
GtkWidget
{
border: @bg_color;
}
#mymenu:hover
{
color:@fg_color;
background: @bg_color;
-unico-inner-stroke-width: 0;
}
In this example, I am setting the hover color of a single GtkMenuItem to be the same as the background color, but if you want to set the color to something else, you'd have to change the background
property as per your needs.
Result, a working MenuItem without a hover color
Here is the full Python code:
from gi.repository import Gtk, Gdk
import sys
class TrayIcon:
def __init__(self):
self.statusicon = Gtk.StatusIcon()
self.statusicon.set_from_stock(Gtk.STOCK_MEDIA_PLAY)
self.statusicon.connect("popup-menu", self.OnShowPopupMenu)
self.statusicon.set_tooltip_text("HELLO")
window = Gtk.Window()
def OnShowPopupMenu(self, icon, button, time):
display = Gdk.Display.get_default()
screen = display.get_default_screen()
css_provider = Gtk.CssProvider()
gtk3Css = """GtkMenuItem {
border:@bg_color;
background:@bg_color;
}
GtkMenuItem:hover
{
background:@selected_bg_color;
}
GtkWidget
{
border: @bg_color;
}
#mymenu:hover
{
color:@fg_color;
background: @bg_color;
-unico-inner-stroke-width: 0;
}"""
css_provider.load_from_data(gtk3Css)
context = Gtk.StyleContext()
context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
menu = Gtk.Menu()
#menu.set_name('mymenu')
first = self.GetMenuItem("First")
first.set_name('mymenu')
second = self.GetMenuItem("Second")
menu.append(first)
menu.append(second)
menu.show_all()
menu.popup(None, None, lambda w,x: self.statusicon.position_menu(menu, self.statusicon), self.statusicon, 3, time)
def GetMenuItem(self, txt):
menuItem = Gtk.MenuItem()
menuItem.set_label(txt)
menuItem.connect("button_press_event", self.exit)
return menuItem
def exit(self, a,b):
sys.exit()
TrayIcon()
Gtk.main()
If you wanted to set another background color, you could do this in the CSS above
GtkMenuItem:hover
{
background:purple;
-unico-inner-stroke-width: 0;
}
(or do it in #mymenu:hover)
In conclusion, I think this may have been a problem limited to Ubuntu 12.04 or GTK 3.4.2 which I determined by running,
pkg-config --modversion gtk+-3.0
But I do not have the expertise to determine the origin of this problem.
Well it's C not python, but this works for me. I named the menu "mymenu" that way you can style it without using GtkLabel which would affect any other labels in the application.
/* COMPILE WITH: gcc -Wall -o icon3 `pkg-config --cflags --libs gtk+-3.0` icon3.c */
#include <gtk/gtk.h>
#include <string.h> /* for CSS */
static void cb_left_click(GtkStatusIcon *icon, gpointer data)
{
static GtkWidget *window = NULL;
if (window == NULL) {
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Status Icon");
g_signal_connect( window, "delete-event", G_CALLBACK(gtk_main_quit), NULL );
gtk_widget_show(window);
}
}
static void cb_right_click(GtkStatusIcon *icon, int button, int time, gpointer data)
{
GtkWidget *menu;
menu = gtk_menu_new ();
gtk_widget_set_name(GTK_WIDGET(menu),"mymenu");
GtkWidget *item1 = gtk_menu_item_new_with_label("First");
GtkWidget *item2 = gtk_menu_item_new_with_label("Second");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item1);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item2);
gtk_widget_show_all(menu);
gtk_menu_popup(GTK_MENU(menu),
NULL,
NULL,
gtk_status_icon_position_menu,
icon,
button,
time);
}
int main(int argc, char *argv[])
{
GtkStatusIcon *icon;
/*-- CSS ------------------*/
GtkCssProvider *provider;
GdkDisplay *display;
GdkScreen *screen;
/*---------------------------*/
gtk_init(&argc, &argv);
icon = gtk_status_icon_new_from_stock (GTK_STOCK_MEDIA_PLAY);
g_signal_connect (G_OBJECT(icon), "activate", G_CALLBACK(cb_left_click), NULL);
g_signal_connect (G_OBJECT(icon), "popup-menu", G_CALLBACK(cb_right_click), NULL);
/*---------------- CSS ----------------------------------------------------------------------------------------------------*/
provider = gtk_css_provider_new ();
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
gsize bytes_written, bytes_read;
const gchar* home = "/home/mike/icon3.css";
GError *error = 0;
gtk_css_provider_load_from_path (provider,
g_filename_to_utf8(home, strlen(home),
&bytes_read, &bytes_written, &error),
NULL);
g_object_unref (provider);
/*-------------------------------------------------------------------------------------------------------------------------*/
gtk_main();
return 0;
}
Css file:
#mymenu {
background-color: white;
color: green;
font-weight:bold;
}
#mymenu :hover {
background-color: red;
color: blue;
font-weight:bold;
}
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