You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GTK3中实现子控件的平滑圆角效果

GTK3中子控件平滑圆角抗锯齿实现问题

我希望实现子控件的平滑圆角,使其与主窗口的圆角匹配。由于GTK3无法直接将子控件裁剪到主窗口边框,我采用了区域裁剪,但边角呈现锯齿状。请问在GTK3中是否有带抗锯齿的实现方式?

以下是我使用的代码:

#include <QApplication>
#include <QWidget>
#pragma push_macro("signals")
#undef signals
#include <gtk/gtk.h>
#include <gtk/gtkx.h>
#include <cairo.h>
#pragma pop_macro("signals")

static void set_rounded_corners(GtkWidget *widget, double radius)
{
    if (GdkWindow *gdk_window = gtk_widget_get_window(widget)) {
        int width = gtk_widget_get_allocated_width(widget);
        int height = gtk_widget_get_allocated_height(widget);

        cairo_surface_t *sfc = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
        cairo_t *cr = cairo_create(sfc);

        cairo_set_antialias(cr, CAIRO_ANTIALIAS_BEST);
        cairo_set_source_rgba(cr, 1, 1, 1, 1);
        cairo_move_to(cr, radius, 0);
        cairo_arc(cr, width - radius, radius, radius, -G_PI_2, 0);
        cairo_arc(cr, width - radius, height - radius, radius, 0, G_PI_2);
        cairo_arc(cr, radius, height - radius, radius, G_PI_2, G_PI);
        cairo_arc(cr, radius, radius, radius, G_PI, -G_PI_2);
        cairo_close_path(cr);
        cairo_fill(cr);

        cairo_surface_t *sfc_tgt = cairo_get_target(cr);
        cairo_surface_flush(sfc_tgt);

        cairo_region_t *mask = gdk_cairo_region_create_from_surface(sfc_tgt);
        gdk_window_shape_combine_region(gdk_window, mask, 0, 0);

        cairo_region_destroy(mask);
        cairo_destroy(cr);
        cairo_surface_destroy(sfc);
    }
}

static void on_size_allocate(GtkWidget *widget, GdkRectangle*, gpointer)
{
    set_rounded_corners(widget, 8);
}

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

    gtk_init(&argc, &argv);

    GtkWidget *top_level_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_type_hint(GTK_WINDOW(top_level_window), GdkWindowTypeHint::GDK_WINDOW_TYPE_HINT_NORMAL);
    gtk_window_set_position(GTK_WINDOW(top_level_window), GtkWindowPosition::GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(top_level_window), 400, 300);
    g_signal_connect(top_level_window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    gtk_widget_set_app_paintable(top_level_window, TRUE);
    GdkScreen *scr = gtk_widget_get_screen(top_level_window);
    if (GdkVisual *vis = gdk_screen_get_rgba_visual(scr))
        gtk_widget_set_visual(top_level_window, vis);

    GtkWidget *header = gtk_header_bar_new();
    gtk_window_set_titlebar(GTK_WINDOW(top_level_window), header);
    gtk_widget_destroy(header);

    GtkWidget *socket = gtk_socket_new();
    gtk_container_add(GTK_CONTAINER(top_level_window), socket);

    g_signal_connect(G_OBJECT(socket), "size-allocate", G_CALLBACK(on_size_allocate), NULL);

    QWidget underlay;
    underlay.setStyleSheet("background: #ffffff;");
    underlay.createWinId();
    gtk_socket_add_id(GTK_SOCKET(socket), (Window)underlay.winId());

    gtk_widget_show_all(top_level_window);
    underlay.show();

    return app.exec();
}

已更新代码:补充缺失代码以支持编译。

当前效果:上边角可见撕裂边缘:
效果截图

内容的提问来源于stack exchange,提问作者Helg1980

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 00:42:01