如何让Gtk +窗口背景透明?

我想让Gtk +窗口的背景透明,以便只有窗口中的窗口小部件可见。 我找到了一些教程:

http://mikehearn.wordpress.com/2006/03/26/gtk-windows-with-alpha-channels/

http://macslow.thepimp.net/?p=26

但他们似乎都倾听“暴露”事件,然后委托开罗进行渲染。 这意味着不会渲染添加到窗口的其他窗口小部件(例如,我也尝试向窗口添加按钮)。

我看到GtkWidget上有一个方法modify-bg: http : //library.gnome.org/devel/gtk/stable/GtkWidget.html#gtk-widget-modify-bg

但是,GdkColor似乎不接受透明度参数: http : //library.gnome.org/devel/gdk/stable/gdk-Colormaps-and-Colors.html

我也尝试过GtkWindow.set_opacity方法,但这也设置了窗口内容的不透明度,这不是我想要的。

我很感激任何人都可以提供任何指导。

我更改了alphademo示例以绘制按钮而不是红色圆圈。

此应用程序在400×400透明窗口上绘制按钮。

当您单击窗口时,应用程序显示/隐藏标题栏。

#include  #include  #include  static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer user_data); static gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data); static void clicked(GtkWindow *win, GdkEventButton *event, gpointer user_data); int main(int argc, char **argv) { gtk_init(&argc, &argv); GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 400, 400); gtk_window_set_title(GTK_WINDOW(window), "Alpha Demo"); g_signal_connect(G_OBJECT(window), "delete-event", gtk_main_quit, NULL); gtk_widget_set_app_paintable(window, TRUE); g_signal_connect(G_OBJECT(window), "expose-event", G_CALLBACK(expose), NULL); g_signal_connect(G_OBJECT(window), "screen-changed", G_CALLBACK(screen_changed), NULL); gtk_window_set_decorated(GTK_WINDOW(window), FALSE); gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(clicked), NULL); GtkWidget* fixed_container = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window), fixed_container); GtkWidget* button = gtk_button_new_with_label("button1"); gtk_widget_set_size_request(button, 100, 100); gtk_container_add(GTK_CONTAINER(fixed_container), button); screen_changed(window, NULL, NULL); gtk_widget_show_all(window); gtk_main(); return 0; } gboolean supports_alpha = FALSE; static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer userdata) { /* To check if the display supports alpha channels, get the colormap */ GdkScreen *screen = gtk_widget_get_screen(widget); GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen); if (!colormap) { printf("Your screen does not support alpha channels!\n"); colormap = gdk_screen_get_rgb_colormap(screen); supports_alpha = FALSE; } else { printf("Your screen supports alpha channels!\n"); supports_alpha = TRUE; } gtk_widget_set_colormap(widget, colormap); } static gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer userdata) { cairo_t *cr = gdk_cairo_create(widget->window); if (supports_alpha) cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */ else cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */ /* draw the background */ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); cairo_destroy(cr); return FALSE; } static void clicked(GtkWindow *win, GdkEventButton *event, gpointer user_data) { /* toggle window manager frames */ gtk_window_set_decorated(win, !gtk_window_get_decorated(win)); } 

在Ubuntu 10.04上编译:

 gcc alpha.c -o alpha -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -lgtk-x11-2.0 

谢谢你的回答。 我在python + GTK3中重写了代码:

 #!/usr/bin/python3 from gi.repository import Gtk from gi.repository import Gdk import cairo supports_alpha = False def screen_changed(widget, old_screen, userdata=None): global supports_alpha screen = widget.get_screen() visual = screen.get_rgba_visual() if visual is None: print("Your screen does not support alpha channels!") visual = screen.get_system_visual() supports_alpha = False else: print("Your screen supports alpha channels!") supports_alpha = True widget.set_visual(visual) def expose_draw(widget, event, userdata=None): global supports_alpha cr = Gdk.cairo_create(widget.get_window()) if supports_alpha: print("setting transparent window") cr.set_source_rgba(1.0, 1.0, 1.0, 0.0) else: print("setting opaque window") cr.set_source_rgb(1.0, 1.0, 1.0) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() return False def clicked(window, event, userdata=None): # toggle window manager frames window.set_decorated(not window.get_decorated()) if __name__ == "__main__": window = Gtk.Window() window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(400, 400) window.set_title("Alpha Demo") window.connect("delete-event", Gtk.main_quit) window.set_app_paintable(True) window.connect("draw", expose_draw) window.connect("screen-changed", screen_changed) window.set_decorated(False) window.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) window.connect("button-press-event", clicked) fixed_container = Gtk.Fixed() window.add(fixed_container) button = Gtk.Button.new_with_label("button1") button.set_size_request(100, 100) fixed_container.add(button) screen_changed(window, None, None) window.show_all() Gtk.main() 

感谢代码,正是我正在寻找的,虽然它需要被修改为工作GTK3。 此外,需要将expose-event更改为’draw’事件以使其正常工作。 所以这是我为GTK3修改的代码贡献:

 #include  #include  #include  static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer user_data); static gboolean expose_draw(GtkWidget *widget, GdkEventExpose *event, gpointer userdata); static void clicked(GtkWindow *window, GdkEventButton *event, gpointer user_data); int main(int argc, char **argv) { gtk_init(&argc, &argv); GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 400, 400); gtk_window_set_title(GTK_WINDOW(window), "Alpha Demo"); g_signal_connect(G_OBJECT(window), "delete-event", gtk_main_quit, NULL); gtk_widget_set_app_paintable(window, TRUE); g_signal_connect(G_OBJECT(window), "draw", G_CALLBACK(expose_draw), NULL); g_signal_connect(G_OBJECT(window), "screen-changed", G_CALLBACK(screen_changed), NULL); gtk_window_set_decorated(GTK_WINDOW(window), FALSE); gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(clicked), NULL); GtkWidget* fixed_container = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window), fixed_container); GtkWidget* button = gtk_button_new_with_label("button1"); gtk_widget_set_size_request(button, 100, 100); gtk_container_add(GTK_CONTAINER(fixed_container), button); screen_changed(window, NULL, NULL); gtk_widget_show_all(window); gtk_main(); return 0; } gboolean supports_alpha = FALSE; static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer userdata) { GdkScreen *screen = gtk_widget_get_screen(widget); GdkVisual *visual = gdk_screen_get_rgba_visual(screen); if (!visual) { printf("Your screen does not support alpha channels!\n"); visual = gdk_screen_get_system_visual(screen); supports_alpha = FALSE; } else { printf("Your screen supports alpha channels!\n"); supports_alpha = TRUE; } gtk_widget_set_visual(widget, visual); } static gboolean expose_draw(GtkWidget *widget, GdkEventExpose *event, gpointer userdata) { cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget)); if (supports_alpha) { printf("setting transparent window\n"); cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); } else { printf("setting opaque window\n"); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); } cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); cairo_destroy(cr); return FALSE; } static void clicked(GtkWindow *window, GdkEventButton *event, gpointer user_data) { /* toggle window manager frames */ gtk_window_set_decorated(window, !gtk_window_get_decorated(window)); } 

这是我在Ubuntu 15.04上编译的方式:

 gcc alpha.c -o alpha `pkg-config --cflags --libs glib-2.0` `pkg-config --cflags --libs gtk+-3.0` 

希望这有助于其他人试图让它在GTK3上运行。