我目前正在尝试使用C学习GTK + 3 / cairo。 我写了一个小应用程序,它使用cairo在gtk绘图区域绘制一个表面和针。
到目前为止效果很好,我尝试创建多个绘图区域(多个仪表) 对于draw事件都具有相同的回调函数,这也适用于静态值。
现在我的问题是,我希望能够使用自己的值绘制多个仪表。但是我怎么知道在我的回调函数中哪个量程(绘图区域)发出了绘制信号? 我想这还包括如何为量表“创建和存储”数据,以便可以从绘图回调中获取它们的属性。
我应该创建一个结构来保存量表的数据,并创建其中的多个。这就是我通过查看使用GTK的各种项目所收集到的内容,但对于我来说,完全理解它的工作方式对我来说太复杂了。
这是我创建绘图区域的方式:
gaugearea1 = gtk_drawing_area_new();
gtk_box_pack_start(GTK_BOX(hbox), gaugearea1, FALSE, FALSE, 5);
gtk_widget_set_size_request(gaugearea1, 300, 300);
gtk_widget_realize(gaugearea1);
g_signal_connect(gaugearea1, "draw", G_CALLBACK(draw_event), NULL);
回调函数就是这样编写的,相当标准。
static gboolean draw_event(GtkWidget *widget, cairo_t *cr)
{
GdkWindow *win;
win = gtk_widget_get_window(widget);
// Draw all arcs/lines using cr
}
非常感谢任何有关如何处理此类问题的提示。
答案 0 :(得分:5)
发出信号的GtkDrawingArea
只是您在回调中收到的widget
。如果需要,只需将其转换为适当的类型。
但请仔细查看draw
信号中的文档:
gboolean user_function (GtkWidget *widget,
CairoContext *cr,
gpointer user_data) : Run Last
您的draw_event
函数缺少最后一个参数gpointer user_data
。
这是使用NULL
调用的最后g_signal_connect()
参数。
所以你可以在这里放一个指向结构的指针,其中包含你需要的所有数据。
或者您可以使用g_object_set_data()
函数附加指向窗口小部件的指针,但我不建议将其用于这样一个简单的应用程序。
如果您有一定数量的仪表,一切都很好:只需创建相同数量的结构,但如果您的仪表数量是动态的,则必须在头部创建结构,因此出现了一个新问题:你释放数据了吗?答案在g_signal_connect_data()
:这个函数接收一个额外的回调,当不再需要结构时调用它。
类似下面的内容:
struct GaugeData
{
/* your data here */
};
static void gauge_data_free(gpointer ptr, GClosure *clo)
{
struct GaugeData *data = ptr;
/* free extra resources, if needed */
g_free(data);
}
static gboolean draw_event(GtkWidget *widget, cairo_t *cr, gpointer ptr)
{
struct GaugeData *data = ptr;
// Draw all arcs/lines using cr and data
}
void CreateOneGauge()
{
gaugearea1 = gtk_drawing_area_new();
struct GaugeData *data = g_new(GaugeData, 1);
/* init the data */
/* ... */
g_signal_connect_data(gaugearea1, "draw", G_CALLBACK(draw_event),
data, gauge_data_free, 0);
}