我目前正在尝试使用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);
Run Code Online (Sandbox Code Playgroud)
并且回调函数是这样编写的,非常标准.
static gboolean draw_event(GtkWidget *widget, cairo_t *cr)
{
GdkWindow *win;
win = gtk_widget_get_window(widget);
// Draw all arcs/lines using cr
}
Run Code Online (Sandbox Code Playgroud)
关于如何处理这样的事情的任何提示将不胜感激.
该GtkDrawingArea发射信号仅仅是widget你在你的回调接收.如果需要,只需将其转换为适当的类型.
但请仔细查看draw信号中的文档:
gboolean user_function (GtkWidget *widget,
CairoContext *cr,
gpointer user_data) : Run Last
Run Code Online (Sandbox Code Playgroud)
你的draw_event函数缺少最后一个参数,即gpointer user_data.
这就是使用NULL调用的最后一个参数g_signal_connect().所以你可以在这里放一个指向结构的指针,其中包含你需要的所有数据.
或者您可以使用该g_object_set_data()函数附加指向窗口小部件的指针,但我不建议将其用于这样一个简单的应用程序.
如果您有一定数量的仪表,一切都很好:只需创建相同数量的结构,但如果您的仪表数量是动态的,您必须在头部创建结构,因此出现了一个新问题:何时自由数据?答案是g_signal_connect_data():这个函数接收一个额外的回调,当不再需要struct时调用它.
像下面这样的东西:
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);
}
Run Code Online (Sandbox Code Playgroud)