代码之家  ›  专栏  ›  技术社区  ›  jbeard4

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

  •  13
  • jbeard4  · 技术社区  · 14 年前

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

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

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

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

    http://library.gnome.org/devel/gdk/stable/gdk-Colormaps-and-Colors.html

    我很感激任何人能在这方面提供指导。

    4 回复  |  直到 11 年前
        1
  •  15
  •   Afriza N. Arief    5 年前

    我改变了 alphademo

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

    #include <gtk/gtk.h>
    #include <gdk/gdkscreen.h>
    #include <cairo.h>
    
    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));
    }
    

    在Ubuntu10.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
    
        2
  •  8
  •   draekko    9 年前

    谢谢你的代码,正是我所寻找的,虽然它需要修改工作的GTK3。此外,需要将expose事件更改为“draw”事件才能使其正常工作。下面是我为GTK3修改的代码:

    #include <gtk/gtk.h>
    #include <gdk/gdkscreen.h>
    #include <cairo.h>
    
    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));
    }
    

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

    希望这有助于其他人试图让它工作在GTK3。

        3
  •  8
  •   Afriza N. Arief    5 年前

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

    #!/usr/bin/env python3
    
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk, 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()
    
        4
  •  2
  •   Afriza N. Arief    5 年前

    https://github.com/gotk3/gotk3

    package main
    
    import (
        "github.com/gotk3/gotk3/cairo"
        "github.com/gotk3/gotk3/gdk"
        "github.com/gotk3/gotk3/gtk"
        "log"
    )
    
    var alphaSupported = false
    
    func main() {
        gtk.Init(nil)
    
        win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
        if err != nil {
            log.Fatal("Unable to create window:", err)
        }
        win.SetTitle("Simple Example")
        win.Connect("destroy", func() {
            gtk.MainQuit()
        })
    
        // Needed for transparency
        win.SetAppPaintable(true)
    
        win.Connect("screen-changed", func (widget *gtk.Widget, oldScreen *gdk.Screen, userData ...interface{}) {
            screenChanged(widget)
        })
        win.Connect("draw", func (window *gtk.Window, context *cairo.Context) {
            exposeDraw(window, context)
        })
    
        l, err := gtk.LabelNew("I'm transparent !")
        if err != nil {
            log.Fatal("Unable to create label:", err)
        }
    
        win.Add(l)
        win.SetDefaultSize(800, 600)
    
        screenChanged(&win.Widget)
    
        win.ShowAll()
        gtk.Main()
    }
    
    func screenChanged(widget *gtk.Widget) {
        screen, _ := widget.GetScreen()
        visual, _ := screen.GetRGBAVisual()
    
        if visual != nil {
            alphaSupported = true
        } else {
            println("Alpha not supported")
            alphaSupported = false
        }
    
        widget.SetVisual(visual)
    }
    
    func exposeDraw(w *gtk.Window, ctx *cairo.Context) {
        if alphaSupported {
            ctx.SetSourceRGBA(0.0, 0.0, 0.0, 0.25)
        } else {
            ctx.SetSourceRGB(0.0, 0.0, 0.0)
        }
    
        ctx.SetOperator(cairo.OPERATOR_SOURCE)
        ctx.Paint()
    }