立即修改 GTK 按钮样式 / CSS 和 update/refresh
Modify GTK button style / CSS and update/refresh instantly
首先让我说我是一个 GTK 菜鸟,发现自己空降到修改别人的代码 - 其他人已经逃离这个国家到更绿色的地方。
因此,我们有一个 GTK 按钮网格,它们只是一个彩色方块,每个按钮都可以即时修改以更改颜色。
目前程序流程是这样的;
生成 CSS 包含 25 种按钮颜色样式的列表,如下所示:
.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);
并显示我们 window 的按钮。
当我们接到 修改 按钮颜色的调用时,代码只是将该按钮的 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);
}
}
然而,需要发生的是能够将 any 按钮设置为 any RGB 颜色 on- the-fly,我不相信创建 2^24 CSS 样式是最佳途径 ;)
我的想法是,我们改为为每个按钮赋予其 自己的 CSS id 选择器和自己的 RGB 颜色,并简单地修改 [=65= 中的颜色值] 根据需要...但是,我在 GTK 文档中用谷歌搜索了一半,但我看不到任何可以修改 existing CSS 的明显方法并将更改反映在显示的按钮中。
任何人都可以指出我正确的方向吗?
编辑:到目前为止,我发现了几个 potential examples...
这个...
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...
我也不确定其中任何一个是否存在内存泄漏,以及提供程序是静态的还是被销毁/在添加到小部件的上下文后是否可以被释放()...docs/examples 对此似乎含糊不清,有人得到了关于如何 create/curate 在一个应用程序中使用多个供应商的不错的教程吗?
第一个例子对我来说看起来最有希望,虽然一遍又一遍地重写provier似乎有点粗糙?
好吧,我自己想出来了 - 这可能是完全错误的方法,但它有效。
它涉及将 CSS 提供程序(而不是 g_object_deref() 使用后)保存在包含所有按钮信息的全局上下文中。然后每次 over-writing CSS 供应商,TFM 说这完全没问题。
我们必须保留 CSS 提供程序和对它的引用,因为 GTK 似乎缺少很多函数来从对象 back 获取此类信息一旦你创建了它——你可以添加新的、替换的和 destroy/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);
就是这样,它可以工作,而且不会泄漏内存。
首先让我说我是一个 GTK 菜鸟,发现自己空降到修改别人的代码 - 其他人已经逃离这个国家到更绿色的地方。
因此,我们有一个 GTK 按钮网格,它们只是一个彩色方块,每个按钮都可以即时修改以更改颜色。
目前程序流程是这样的;
生成 CSS 包含 25 种按钮颜色样式的列表,如下所示:
.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);
并显示我们 window 的按钮。
当我们接到 修改 按钮颜色的调用时,代码只是将该按钮的 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);
}
}
然而,需要发生的是能够将 any 按钮设置为 any RGB 颜色 on- the-fly,我不相信创建 2^24 CSS 样式是最佳途径 ;)
我的想法是,我们改为为每个按钮赋予其 自己的 CSS id 选择器和自己的 RGB 颜色,并简单地修改 [=65= 中的颜色值] 根据需要...但是,我在 GTK 文档中用谷歌搜索了一半,但我看不到任何可以修改 existing CSS 的明显方法并将更改反映在显示的按钮中。
任何人都可以指出我正确的方向吗?
编辑:到目前为止,我发现了几个 potential examples...
这个...
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...
我也不确定其中任何一个是否存在内存泄漏,以及提供程序是静态的还是被销毁/在添加到小部件的上下文后是否可以被释放()...docs/examples 对此似乎含糊不清,有人得到了关于如何 create/curate 在一个应用程序中使用多个供应商的不错的教程吗?
第一个例子对我来说看起来最有希望,虽然一遍又一遍地重写provier似乎有点粗糙?
好吧,我自己想出来了 - 这可能是完全错误的方法,但它有效。
它涉及将 CSS 提供程序(而不是 g_object_deref() 使用后)保存在包含所有按钮信息的全局上下文中。然后每次 over-writing CSS 供应商,TFM 说这完全没问题。
我们必须保留 CSS 提供程序和对它的引用,因为 GTK 似乎缺少很多函数来从对象 back 获取此类信息一旦你创建了它——你可以添加新的、替换的和 destroy/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);
就是这样,它可以工作,而且不会泄漏内存。