如何在Linux上使gtkwindow背景透明?

时间:2013-05-30 09:33:14

标签: gtk gtk3

我想让背景透明,只有窗口小部件可见。

这是我的代码:

#include <gtk/gtk.h>
int main (int argc, char *argv[])
{
    gtk_init (&argc, &argv);
    GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    // Title
    gtk_window_set_title(GTK_WINDOW (window), "Transparency");
    //gtk_window_set_opacity(GTK_WINDOW(window), 0.5);

    // CSS
    GtkCssProvider *provider = gtk_css_provider_new();
    GdkDisplay *display = gdk_display_get_default();
    GdkScreen *screen = gdk_display_get_default_screen(display);
    gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
    gtk_css_provider_load_from_data(GTK_CSS_PROVIDER (provider),
                                    "GtkWindow {\n"
                                    "   background-color: rgba(0,0,0,0);\n"
                                    "}\n",
                                     -1, NULL);
    g_object_unref (provider);

    // Window
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_resize(GTK_WINDOW(window), 400, 300);
    gtk_widget_show_all(window);

    gtk_main();
    return 0;
}

我使用gtk3。程序执行时,它只显示黑色。 CSS(或rgba)函数不起作用。 我尝试使用gtk_window_set_opacity(),但它也只显示黑色。 如何修复代码?

2 个答案:

答案 0 :(得分:11)

我按照评论建议的link,但遗憾的是它是为Gtk 2编写的。我已经为Gtk 3重新编写了。(我使用的是Gtk 3.8,但据我所知,它确实如此不要使用Gtk 3.10中弃用的任何东西。该程序生成一个带有按钮的绿色半透明方块。当然,您可以通过将函数cairo_set_source_rgba的最后一个参数更改为0来使方块完全透明。

注意:我使用以下命令编译它(假设您调用文件transparent.c):

gcc -otransparent transparent.c `pkg-config gtk+-3.0 --libs --cflags`

以下是代码:

C

的版本
/**
 * Original code by: Mike - http://plan99.net/~mike/blog (now a dead link--unable to find it).
 * Modified by karlphillip for StackExchange:
 *     (https://stackoverflow.com/questions/3908565/how-to-make-gtk-window-background-transparent)
 * Re-worked for Gtk 3 by Louis Melahn, L.C., January 30, 2014.
 */

#include <gtk/gtk.h>

static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer user_data);
static gboolean draw(GtkWidget *widget, cairo_t *new_cr, 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), "draw", G_CALLBACK(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)
{
    /* To check if the display supports alpha channels, get the visual */
    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 draw(GtkWidget *widget, cairo_t *cr, gpointer userdata)
{
    cairo_save (cr);

    if (supports_alpha)
    {
        cairo_set_source_rgba (cr, 0.5, 1.0, 0.50, 0.5); /* 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_restore (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));
} 

C ++版本

我包含了一个非常相似的程序,这次是在C ++中为gtkmm编写的。可以使用以下命令编译它:

g++ -otransparent main.cpp transparent.cpp `pkg-config gtkmm-3.0 --cflags --libs` -std=c++11

请注意,我使用了新的C ++ - 11标准中的一些功能,因此您需要一个支持它们的编译器。 (如果没有,则只需在auto关键字出现时使用相应的类型替换它,您可以从函数的定义中找出它。)有三个文件:{{1 }},main.cpptransparent.h

的main.cpp

transparent.cpp

transparent.h

/**
 * main.cpp
 *
 * Code adapted from 'alphademo.c' by Mike
 * (http://plan99.net/~mike/blog--now a dead link--unable to find it.)
 * as modified by karlphillip for StackExchange:
 *     (https://stackoverflow.com/questions/3908565/how-to-make-gtk-window-background-transparent)
 * Re-worked for Gtkmm 3.0 by Louis Melahn, L.C. January 31, 2014.
 */
#include "transparent.h"
#include <gtkmm/application.h>

int main (int argc, char *argv[])
{
    Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example.transparent");

    Transparent transparent;

    //Shows the window and returns when it is closed.
    return app->run(transparent);
}

transparent.cpp

/**
 * transparent.h
 *
 * Code adapted from 'alphademo.c' by Mike
 * (http://plan99.net/~mike/blog--now a dead link--unable to find it.)
 * as modified by karlphillip for StackExchange:
 *     (https://stackoverflow.com/questions/3908565/how-to-make-gtk-window-background-transparent)
 * Re-worked for Gtkmm 3.0 by Louis Melahn, L.C. January 31, 2014.
 */

#ifndef TRANSPARENT_H_
#define TRANSPARENT_H_

#include <iostream>
#include <gtk/gtk.h>
#include <gtkmm/window.h>
#include <gtkmm/button.h>
#include <gtkmm/alignment.h>

class Transparent : public Gtk::Window
{

private:
    std::string _buttonLabel;

public:
    Transparent();
    void set_visual(Glib::RefPtr<Gdk::Visual> visual);
    virtual ~Transparent();

protected:
    // Signal handlers:
    // Note that on_draw is actually overriding a virtual function
    // from the Gtk::Window class. I set it as virtual here in case
    // someone wants to override it again in a derived class.
    void on_button_clicked();
    virtual bool on_draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr);
    void on_screen_changed(const Glib::RefPtr<Gdk::Screen>& previous_screen);
    bool on_window_clicked(GdkEventButton* event);

    // Member widgets:
    Gtk::Alignment _alignment;
    Gtk::Button _button;

    bool _SUPPORTS_ALPHA = false;

};

#endif /* TRANSPARENT_H_ */

希望这有帮助!

答案 1 :(得分:4)

在努力解决同样的问题时,我注意到如果我在show_all函数之后在顶层窗口上调用gtk_window_set_opacity(),那么整个窗口(部分)透明对我来说是有效的。试一试:

gtk_widget_show_all ( window );
gtk_widget_set_opacity (GTK_WIDGET (window), 0.5);

这对你有用吗?