Set the hover background color of a Gtk3 MenuItem

瘦欲@ 提交于 2019-12-04 13:47:58

After a lot of digging, the answer turned out to be somewhat obscure.

  • background-color does not work. I had to use background
  • I also had to use -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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!