c - GTK+2 : Drawing above other widgets transparently

标签 c linux gtk

我被迫使用 Gtk+2。所以请不要讨论切换到 3 或 4。
我需要创建类似于 Gtk3s 的东西 GtkOverlay我需要在其他小部件上绘制透明背景。
我想用 GtkFixed并将我的“普通”小部件放在那里,然后使用 GtkEventBox将颜色图(如果支持)设置为透明后,放在顶部并连接其公开事件。
我得到了一些工作,但它没有预期的结果。它导致事件框变得半透明(如我所愿),但现在显示下方的小部件,但显示窗口下方的所有内容。
到目前为止,这是我的代码(抱歉弄乱了):

#include <gtk/gtk.h>

GtkWidget *window;
GtkWidget *button;
GtkWidget *vbox;
GtkWidget *fixed;  
GtkWidget *event_overlay;
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 exposed (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    cairo_t *cr = gdk_cairo_create(widget->window);
 
    cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5); /* transparent */

    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
    cairo_paint (cr);

    cairo_destroy(cr);

    return TRUE;
}

static void hello( GtkWidget *widget,
                   gpointer   data )
{
    gtk_fixed_put(GTK_FIXED(fixed), event_overlay, 100, 100);
}

static void destroy( GtkWidget *widget,
                     gpointer   data )
{
    gtk_main_quit ();
}

int main( int   argc,
          char *argv[] )
{
  

    gtk_init (&argc, &argv);
    
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    g_signal_connect (window, "destroy",
              G_CALLBACK (destroy), NULL);
              
    button = gtk_button_new_with_label ("Hello World");
    g_signal_connect (button, "clicked",
              G_CALLBACK (hello), NULL);
              
    vbox = gtk_vbox_new(TRUE, 5);
    gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
    
    fixed = gtk_fixed_new();
    gtk_fixed_set_has_window(GTK_FIXED(fixed), TRUE);
    gtk_widget_set_size_request(button, 500, 500);
    gtk_fixed_put(GTK_FIXED(fixed), vbox, 0, 0);
    event_overlay = gtk_event_box_new();
    gtk_widget_set_size_request(event_overlay, 500, 500);
    g_signal_connect(event_overlay, "expose-event", G_CALLBACK(exposed), NULL);
    g_signal_connect(G_OBJECT(window), "screen-changed", G_CALLBACK(screen_changed), NULL);
    gtk_widget_set_app_paintable(window, TRUE);


    gtk_container_add (GTK_CONTAINER (window), fixed);
    screen_changed(window, NULL, NULL);
    gtk_widget_show_all (window);
    gtk_widget_show(event_overlay);
    
    gtk_main ();
    
    return 0;
}
结果如下:
Transparency done wrong

最佳答案

事实证明,GTK+ 2 作者实际上已经预见到了这个用例。有一对非常相似的现成示例包含在 gtk-demo 中。程序,随 GTK+ 2 文档一起分发。两个演示都可以在“屏幕外窗口”节点下找到。
代码有点复杂,所以我不包括在这里;该演示实际上是子类 GtkContainer创建一个新的小部件类,将事件转发到其子项并将其呈现到屏幕外窗口以对呈现结果执行进一步的转换。但是您应该会发现“效果”示例非常容易满足您的需求:您所要做的就是修改 gtk_mirror_bin_expose简单地将屏幕外窗口的内容绘制到容器的真实窗口中,然后在其上绘制半透明叠加层;并调整 gtk_mirror_bin_size_requestgtk_mirror_bin_size_allocate简单地将所有与尺寸相关的信号透明地转发给 child 。

关于c - GTK+2 : Drawing above other widgets transparently,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68373996/

相关文章:

c - fprintf 没有将数据打印到文件中

c++ - 以优雅礼貌的方式在 C++ 中处理 GTK 回调

c - 如何使用 g_timeout_add?

c - 动画窗口图标

c - 如果我们使用 memcpy 将更多数据从源复制到目标,会发生什么?

c - 从 double 到 float 的转换是否总是潜在地调用未定义的行为?

C 标准版本检查

c - 同级 .so 文件中符号的可见性

linux - 如何在 Linux 上更改 tty 组(使用 buildroot 构建)

c - 我如何知道对特定程序使用哪个 exec 命令?