2

我目前正在尝试使用 C 学习 GTK+3/cairo。我编写了一个小应用程序,它使用 cairo 在 gtk 绘图区域上绘制仪表面和针。

到目前为止效果很好,我尝试创建多个绘图区域(多个仪表),它们都具有相同的绘图事件回调函数,这也适用于静态值。

现在我的问题是,我希望能够绘制多个仪表,每个仪表都有自己的值。但是我如何在我的回调函数中知道哪个仪表(绘图区域)发出了绘图信号?我想这还包括我如何为仪表“创建和存储”数据,以便可以从绘图回调中获取它们的属性。

我可能应该创建一个包含仪表数据的结构,并创建多个。这就是我通过查看使用 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
}

任何有关如何处理此类问题的提示将不胜感激。

4

1 回答 1

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);
}
于 2012-06-29T22:09:46.293 回答