修改GTK按钮样式/CSS并立即更新/刷新



让我在序言中说,我是GTK Noob,发现自己被空降到修改别人的代码中——别人已经逃离这个国家,去了更环保的地方。

因此,我们有一个GTK网格按钮,它只是一个彩色正方形,每个按钮都可以随时修改以改变颜色。

目前,程序流程是这样的;

生成包含25个按钮颜色样式列表的CSS,如下所示:

.btn_colour_id_XX{background: #336699}
.btn_colour_id_XX:active{ background: shade(#336699, 0.5) }

然后根据我们想要的颜色为每个按钮附上一个样式:

GtkStyleContext *context = gtk_widget_get_style_context(button);
snprintf(value, 20, "btn_colour_id_%02d", colour_id); // Apply colour_id to button
gtk_style_context_add_class(context, value);

并显示我们充满按钮的窗口。

当我们接到修改按钮颜色的调用时,代码只会将该按钮的CSS样式切换为请求的样式:

snprintf(desired_class, 10, "btn_colour_id_%02d", color_id); // Style we want for button
for (GList *l = classes; l != NULL; l = l->next)
{
char *classname = (char *)l->data;
if (strstr(classname, "btn_colour_id_") == NULL)
{
continue;
}
if (strlen(classname) != strlen(desired_class) || strstr(classname, desired_class) == NULL)
{
g_message("Swapping [%s] colour from %s > %s", name, classname, desired_class);
gtk_style_context_remove_class(context, (const gchar *)l->data);
gtk_style_context_add_class(context, desired_class);
}
}

然而,需要做的是能够将任何按钮设置为任意RGB颜色,并且我不相信创建2^24 CSS样式是实现这一点的最佳途径;(

我的想法是,我们为每个按钮提供其自己的CSS id选择器和自己的RGB颜色,并根据需要简单地修改CSS中的颜色值。。。然而,我已经在谷歌上搜索了GTK文档,我看不到任何明显的方法可以修改现有的CSS,并在显示的按钮中反映出这种变化。

有人能给我指出正确的方向吗?


编辑:到目前为止,我已经找到了几个潜在的例子

这个。。。

static GtkCssProvider* provider = NULL;
static void set_label_color(GtkWidget* label, const char* color)
{
const char* format = "label { color: %s; }";
size_t length = strlen(format) - 2 + 1;
char style[length];
sprintf(style, format, color);
if (provider == NULL) {
// only create and add the provider the first time
provider = gtk_css_provider_new();
gtk_style_context_add_provider(
gtk_widget_get_style_context(label),
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref(provider);
}
gtk_css_provider_load_from_data(provider, style, -1, NULL);
} 

而这个。。。

void set_background_color(GtkWidget *w, gchar *color)
{
GtkCssProvider *gcp;
GtkStyleContext *gsc;
gsc = gtk_widget_get_style_context(w);
const gchar *type = g_type_name (G_TYPE_FROM_INSTANCE (w));
gchar *str = g_strdup_printf ("%s {background-color: %s;}", type,
color);
gcp= gtk_css_provider_new();
gtk_css_provider_load_from_data(gcp, str, -1, 0);
g_free (str);
gtk_style_context_add_provider(gsc, GTK_STYLE_PROVIDER(gcp),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
// I don't know if there is a memory leak here though...

我也不确定这两者中是否存在内存泄漏,以及提供程序是静态的还是被破坏的/在添加到小部件的上下文后可以是free((d。。。文档/示例在这方面似乎很模糊,有人得到了关于如何在应用程序中创建/策划多个提供者的不错教程吗?

第一个例子对我来说似乎最有希望,尽管一遍又一遍地重写提供者似乎有点困难?

好吧,我自己已经想好了——这可能是完全错误的方法,但它有效。

它涉及将CSS提供程序(而不是使用后的g_object_deref(((保存在一个全局上下文中,该上下文包含有关所有按钮的信息。然后每次都简单地重写CSS提供程序,TFM说这完全可以。

我们必须保留CSS提供程序和对它的引用,因为GTK似乎缺少很多函数,一旦你创建了对象,就可以从对象中获取这种排序信息-你可以添加新的、替换的和销毁/deref,但你不能读取现有的;修改它。我想大多数UI都是你写一次,就这样。

上下文:

struct dev_button
{
GtkWidget *btn;
GtkCssProvider *bp;
};

创建按钮:

dbp = &_context->buttons[i]; // Pointer to a dev_button struct
GtkStyleContext *context = gtk_widget_get_style_context(dbp->btn);
dbp->bp = gtk_css_provider_new();

// Create a CSS for this button
snprintf(css, LONG_STR, ".btnid_%02d{background: #%06X}", btnID, colour);

// Convert CSS to provider
gtk_css_provider_load_from_data(dbp->bp, tstr, -1, NULL);

// Add provider to button
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER(dbp->bp), GTK_STYLE_PROVIDER_PRIORITY_USER);

// Give the button the CSS style/class corresponding to the one we just created for it
snprintf(value, SHORT_STR, "btnid_%02d", buttonId); // Sets default colour from table
gtk_style_context_add_class(context, value);

动态更改按钮的颜色:

// Create new CSS
snprintf(temp_css, LONG_STR, ".btnid_%02d{background: #%06X}", btnID, new_colour);
// Re-load into provider
gtk_css_provider_load_from_data(dbp->bp, tstr, -1, NULL);

就是这样,它有效,而且不会泄露内存。

最新更新