多个小部件的C / GTK + 3绘制事件

时间:2012-06-29 20:36:58

标签: c gtk cairo

我目前正在尝试使用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
}

非常感谢任何有关如何处理此类问题的提示。

1 个答案:

答案 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);
}