C / GTK + 3战平多个小部件事件
我目前正在学习使用C. GTK + 3 /开罗
我写了一个小的应用程序中使用开罗其中借鉴了GTK绘图区域轨距面和针。
I am currently trying to learn GTK+3/cairo using C. I have written a small application which draws a gauge face and needle on a gtk drawing area using cairo.
这工作得很好,到目前为止,我已经尝试创建多个绘图区域(多计),这
都对平局事件相同的回调函数,这也与静态值效果很好。
This works well so far, i have tried creating multiple drawing areas (multiple gauges) which all have the same callback function for the draw event, this also works well with static values.
现在我的问题,我想能够得出每个多个仪表与自己的价值观。但我怎么知道在哪个计(绘图区域)发出的信号平局我的回调函数?
我想这也包括我如何创建和存储数据的仪表所以它们的属性可以从抽签回调中获取的。
Now my question, i would like to be able to draw multiple gauges each with their own values. But how do i know in my callback function which gauge (drawing area) emitted the draw signal? I guess this also includes how do i "create and store" data for the gauges so their properties can be fetched from within the draw callback.
我也许应该创建一个保存数据的计一个结构,并创建这些多。这就是我已经通过看使用GTK各种项目云集,但它太复杂,我完全理解它是如何工作的。
I should probably create a struct that holds the data for a gauge, and create multiple of those. That's what i have gathered by looking at various projects that use GTK, but it's too complicated for me to fully understand how it works.
这是我如何创建绘图区域(S):
This is how i create the drawing area(s):
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);
和回调函数是这样写的,pretty标准。
And the callback function is written like this, pretty standard.
static gboolean draw_event(GtkWidget *widget, cairo_t *cr)
{
GdkWindow *win;
win = gtk_widget_get_window(widget);
// Draw all arcs/lines using cr
}
对如何处理这样的事情会大大AP preciated任何提示。
Any tips on how to approach something like this would be greatly appreciated.
的 GtkDrawingArea
发出的信号仅仅是小部件
您收到您的回调。只需将它转换为相应的类型,如果需要的话。
The GtkDrawingArea
that emits the signal is simply the widget
you receive in your callback. Just cast it to the appropriate type, if needed.
但在从文档仔细看的画
信号:
But look carefully at the docs from the draw
signal:
gboolean user_function (GtkWidget *widget,
CairoContext *cr,
gpointer user_data) : Run Last
您 draw_event
函数缺少最后一个参数,在 gpointer USER_DATA
。
Your draw_event
function is missing the last parameter, the gpointer user_data
.
这就是使用调用的最后一个 NULL
参数对 g_signal_connect()
。
所以,你可以把这里的指针,结构与所有你需要的数据。
And that's the use of the last NULL
parameter of the call to g_signal_connect()
.
So you can put here a pointer to a struct with all the data you need.
或者你也可以使用 g_object_set_data()
函数的指针附加到小部件,但我不建议这样一个简单的应用程序。
Or you can use the g_object_set_data()
function to attach a pointer to the widget, but I wouldn't recommend that for such a simple application.
如果你有仪表固定数量的,一切都很好:只要创建相同数量的结构,但如果你的计数量是动态的,你必须创建在头上的结构,所以一个新的问题出现了:当你释放的数据?答案是 g_signal_connect_data()
:这个函数接收一个额外的回调时,不再需要该结构被称为
If you have a fixed number of gauges, all is well: just create the same number of structs, but if your number of gauges is dynamic, you have to create the structs in the head, so a new problem arises: when do you free the data? The answer is in g_signal_connect_data()
: this function receives an additional callback that is called when the struct is no longer needed.
有点像follwoing:
Something like the follwoing:
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);
}