gtk - 将一个小的 gtk3 样本从 gtk 3.18 迁移到 gtk 3.22
问题描述
我正在开发一些应用程序,我们通过调用“gtk_render_option”、“gtk_render_check”等来绘制“RadioButton”、“CheckButton”等小部件。我们的应用程序在 gtk 3.18 上运行良好,但在 gtk 3.22 上,小部件未正确绘制。我已经完成了 3.20 中对主题所做的更改,并尝试在我的应用程序中进行一些更改,但我无法准确理解我需要做什么。
我创建了一个小示例,在其中使用 gtk_render_option API 绘制“RadioButton”。这在 gtk-3.18 中对我来说很好,但在 gtk 3.22 中导致问题。我附上图片和代码以供参考。如果这里有人可以指导我“如何使这个小型演示在 gtk 3.22 上运行”,那就太好了。我应该能够自己处理其余的事情。我可以提供所需的任何进一步信息。
注意:我在 gtk_style_context_add_class API 中尝试了“radio”和“radiobutton”。两者都不适合我。
使用 gtk 3.18 输出
使用 gtk 3.22 输出
代码
#include <string.h>
#include <gtk/gtk.h>
static gboolean
draw_cb_options (GtkWidget *widget, cairo_t *cr)
{
GtkStyleContext *context;
context = gtk_widget_get_style_context (widget);
gtk_style_context_save (context);
gtk_style_context_add_class (context, "radio");
gtk_style_context_set_state (context, 0);
gtk_render_option (context, cr, 10, 50, 40, 40);
gtk_style_context_set_state (context, GTK_STATE_FLAG_CHECKED);
gtk_render_option (context, cr, 70, 50, 40, 40);
gtk_style_context_set_state (context, GTK_STATE_FLAG_INCONSISTENT);
gtk_render_option (context, cr, 120, 50, 40, 40);
gtk_style_context_set_state (context, GTK_STATE_FLAG_INSENSITIVE);
gtk_render_option (context, cr, 170, 50, 40, 40);
gtk_style_context_restore (context);
return TRUE;
}
int main (int argc, char *argv[])
{
GtkWidget *window;
GtkStyleContext *context;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "draw", G_CALLBACK (draw_cb_options), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
解决方案
GtkDrawingArea 用于在调用 ::draw 处理程序之前隐式渲染主题背景。这已不再是这种情况。如果您依赖主题提供的背景,请
gtk_render_background()
从 ::draw 处理程序调用。
即使调用gtk_render_background
draw 函数也没有什么区别。下面的示例是基于 gtk3-demo 的外国画图,我尽力简化,但仍然需要经历很多才能完成你需要的。
#include <gtk/gtk.h>
#include <string.h>
static GtkStyleContext *
get_style (GtkStyleContext *parent,
const char *selector)
{
GtkWidgetPath *path;
GtkStyleContext *context;
if (parent)
path = gtk_widget_path_copy (gtk_style_context_get_path (parent));
else
path = gtk_widget_path_new ();
gtk_widget_path_append_type (path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name (path, -1, selector);
context = gtk_style_context_new ();
gtk_style_context_set_path (context, path);
gtk_style_context_set_parent (context, parent);
/* Unfortunately, we have to explicitly set the state again here for it to take effect */
gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1));
gtk_widget_path_unref (path);
return context;
}
static void
draw_style_common (GtkStyleContext *context,
cairo_t *cr,
gint x,
gint y,
gint width,
gint height,
gint *contents_x,
gint *contents_y,
gint *contents_width,
gint *contents_height)
{
GtkBorder margin, border, padding;
int min_width, min_height;
gtk_style_context_get_margin (context, gtk_style_context_get_state (context), &margin);
gtk_style_context_get_border (context, gtk_style_context_get_state (context), &border);
gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &padding);
gtk_style_context_get (context, gtk_style_context_get_state (context),
"min-width", &min_width,
"min-height", &min_height,
NULL);
x += margin.left;
y += margin.top;
width -= margin.left + margin.right;
height -= margin.top + margin.bottom;
width = MAX (width, min_width);
height = MAX (height, min_height);
gtk_render_background (context, cr, x, y, width, height);
gtk_render_frame (context, cr, x, y, width, height);
if (contents_x)
*contents_x = x + border.left + padding.left;
if (contents_y)
*contents_y = y + border.top + padding.top;
if (contents_width)
*contents_width = width - border.left - border.right - padding.left - padding.right;
if (contents_height)
*contents_height = height - border.top - border.bottom - padding.top - padding.bottom;
}
static void
query_size (GtkStyleContext *context,
gint *width,
gint *height)
{
GtkBorder margin, border, padding;
int min_width, min_height;
gtk_style_context_get_margin (context, gtk_style_context_get_state (context), &margin);
gtk_style_context_get_border (context, gtk_style_context_get_state (context), &border);
gtk_style_context_get_padding (context, gtk_style_context_get_state (context), &padding);
gtk_style_context_get (context, gtk_style_context_get_state (context),
"min-width", &min_width,
"min-height", &min_height,
NULL);
min_width += margin.left + margin.right + border.left + border.right + padding.left + padding.right;
min_height += margin.top + margin.bottom + border.top + border.bottom + padding.top + padding.bottom;
*width = MAX (*width, min_width);
*height = MAX (*height, min_height);
}
static void
draw_radio (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
GtkStateFlags state)
{
GtkStyleContext *button_context, *check_context;
gint contents_x, contents_y, contents_width, contents_height;
gint width = 0, height = 0;
/* This information is taken from the GtkRadioButton docs, see "CSS nodes" */
button_context = get_style (NULL, "radiobutton");
check_context = get_style (button_context, "radio");
gtk_style_context_set_state (check_context, state);
query_size (button_context, &width, &height);
query_size (check_context, &width, &height);
draw_style_common (button_context, cr, x, y, width, height, NULL, NULL, NULL, NULL);
draw_style_common (check_context, cr, x, y, width, height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_option (check_context, cr, contents_x, contents_y, contents_width, contents_height);
g_object_unref (check_context);
g_object_unref (button_context);
}
static gboolean
draw_cb (GtkWidget *widget,
cairo_t *cr)
{
draw_radio (widget, cr, 10, 10, GTK_STATE_FLAG_NORMAL);
draw_radio (widget, cr, 50, 50, GTK_STATE_FLAG_CHECKED);
draw_radio (widget, cr, 100, 100, GTK_STATE_FLAG_INCONSISTENT);
draw_radio (widget, cr, 150, 150, GTK_STATE_FLAG_INSENSITIVE);
return FALSE;
}
int main (int argc, char *argv[])
{
GtkWidget *box, *window, *da;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_container_add (GTK_CONTAINER (window), box);
g_signal_connect (box, "draw", G_CALLBACK (draw_cb), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
推荐阅读
- ios - ios APP被杀死firebase时无法在注册期间删除用户
- jpa - Open JPA Query 在 DB2 中第二次执行失败(因为 byte[] 参数)
- h.264 - H.264 RTP 带内参数集变化
- c++ - 使用 reinterpret_cast (C++) 从存储在 char 数组中的二进制文件中读取值
- sql - SQL子查询选择具有相同的分组依据
- javascript - Webpack 的 CONST 在什么范围内
- excel - 使用多个 vlookup 的条件格式
- angular - Angular 6 中的 Http 错误处理
- typescript - 在打字稿中定义名称值查找
- c# - 错误:为 Microsoft.Office.Interop.Excel.Application 实例化对象时出现 800700c1