修改 GTK 按钮样式/CSS 并立即更新/刷新
Posted
技术标签:
【中文标题】修改 GTK 按钮样式/CSS 并立即更新/刷新【英文标题】:Modify GTK button style / CSS and update/refresh instantly 【发布时间】:2020-10-22 13:04:51 【问题描述】:让我先说我是 GTK Noob,发现自己被空降到修改别人的代码 - 其他人已经逃离这个国家到更环保的土地。
所以,我们有一个 GTK 按钮网格,它只是一个彩色方块,每个按钮都可以即时修改以改变颜色。
目前,程序流程是这样的;
生成包含 25 种按钮颜色样式列表的 CSS,如下所示:
.btn_colour_id_XXbackground: #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);
并显示我们的充满按钮的窗口。
当我们调用 modify 按钮颜色时,代码只是将该按钮的 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 颜色,并根据需要简单地修改 CSS 中的颜色值......但是,我已经用谷歌搜索了一半死看着 GTK 文档,我看不到任何明显的方法可以修改 现有的 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...
我也不确定其中任何一个是否存在内存泄漏,以及提供程序是静态的还是被破坏/在添加到小部件的上下文后是否可以释放()d...文档/示例似乎对此含糊其辞,任何人都有关于如何在应用程序中创建/管理多个提供者的不错的教程?
第一个示例对我来说看起来最有希望,尽管一遍又一遍地重写 provier 似乎有点粗糙?
【问题讨论】:
所以基本上只要你得到正确的 modify_color 信号,你只想修改 gtk_button 颜色到你的 25 种或更多颜色吗?还是你也在改变按钮样式? 我希望能够将任何单个按钮修改为 any RGB 颜色,而不是 1-of-25,而是 1-of-16777215。更广泛地说,只是能够在代码运行时修改 GTK CSS——感觉就像我为每个按钮分配了自己的 CSS ID 并在屏幕 CSS 中定义了样式,我应该能够只在飞,但我没有看到实现这一目标的直接方法,可能是因为我对 GTK 缺乏经验。 【参考方案1】:好的,我自己想通了 - 这可能是完全错误的方法,但它确实有效。
它涉及将 CSS 提供程序(而不是使用后的 g_object_deref())保存在包含所有按钮信息的全局上下文中。然后每次都简单地覆盖 CSS 提供程序,TFM 说这非常好。
我们必须保留 CSS 提供程序和它的引用,因为 GTK 似乎缺少很多函数来从对象中获取此类信息添加新的、替换的和销毁/取消引用,但你不能读回现有的并修改它。我猜大多数 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_%02dbackground: #%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_%02dbackground: #%06X", btnID, new_colour);
// Re-load into provider
gtk_css_provider_load_from_data(dbp->bp, tstr, -1, NULL);
就是这样,它可以工作,而且不会泄漏内存。
【讨论】:
以上是关于修改 GTK 按钮样式/CSS 并立即更新/刷新的主要内容,如果未能解决你的问题,请参考以下文章
同事打开两个JSP网页A和B,在其中一个A网页中修改数据,按"提交"之后,B网页要立即刷新,更新数据。