【问题标题】:C/GTK+3 draw event for multiple widgets多个小部件的 C/GTK+3 绘制事件
【发布时间】:2012-06-29 20:36:57
【问题描述】:

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

任何关于如何处理此类事情的提示将不胜感激。

【问题讨论】:

    标签: c gtk cairo


    【解决方案1】:

    发出信号的GtkDrawingArea 就是您在回调中收到的widget。如果需要,只需将其转换为适当的类型即可。

    但请仔细查看来自draw 信号的文档:

    “绘制”信号

    gboolean     user_function                  (GtkWidget    *widget,
                                                CairoContext *cr,
                                                gpointer      user_data) : Run Last
    

    您的draw_event 函数缺少最后一个参数gpointer user_data

    这就是调用g_signal_connect() 的最后一个NULL 参数。 因此,您可以在此处放置一个指向包含您需要的所有数据的结构的指针。

    或者您可以使用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);
    }
    

    【讨论】:

    • 感谢您的精彩回答,我将暂时使用固定数量的仪表,稍后再看看动态创建它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多