搜索

Google
 

星期四, 三月 08, 2007

gtk+开发中的几个小经验

1、在gtk+开发过程中,我们经常需要在event handler中来访问该窗口中的某些控件的信息,通常习惯于整一大堆全局变量,其实还有更好的方式,在glib的实现中我们可以通过g_object_set_data和g_object_get_data给一个GObject对象绑定自定义的数据及属性,g_object_set_data_full还可以在对象释放资源时通知你的回调函数来做资源释放处理,这样我们就可以给event handler传递一个窗口对象指针就行了,其它的数据及控件信息可以通过窗口对象得到我们想要的东西。

2、某些对象并未提供所有属性的存取方法,但只要是通过GObject继承下来的对象均可采用g_object_set、g_object_set_property及g_object_get、g_object_get_property来存取这些属性,如给TreeView中某一列的值要求居右则可以对gtk_cell_renderer_text_new()产生的GtkCellRenderer对象调用g_object_set(renderer, "xalign", 1.0, NULL)来达到居右的效果。

3、使用g_idle_add及g_timeout_add等函数中的时候一定要小心,由于代码延后执行,因此一定要保证其数据的生命周期,如下面的例子是我在开发一个项目应用中遇到的问题(注释掉的代码即为出现问题之后的修正代码),传递的Python对象到代码执行的时候已经被释放掉了,因此出现了比较奇怪的现象:如果连续调用这个函数两次,结果加进去的两行信息全部都是最后一次的数据,当然可能还会有更奇特的现象发生。

static gboolean
_etc_main_win_add_trans(gpointer data)
{
PyObject *args = data;
if (PyTuple_Size(args) != lv_columns)
return FALSE;

GtkWidget *listview;
GtkTreeModel *model;
GtkTreeIter iter;
int i;
GValue value;
PyObject *obj;

listview = GTK_WIDGET(g_object_get_data(G_OBJECT(main_window), "trans_list"));
model = gtk_tree_view_get_model(GTK_TREE_VIEW(listview));
gtk_list_store_append(GTK_LIST_STORE(model), &iter);
for (i = 0; i < lv_columns; ++i) {
memset(&value, 0, sizeof(value));
g_value_init(&value, lv_types[i]);
obj = PyTuple_GetItem(args, i);
switch(lv_types[i]) {
case G_TYPE_INT:
if (PyInt_Check(obj))
g_value_set_int(&value, PyInt_AsLong(obj));
break;

case G_TYPE_LONG:
if (PyLong_Check(obj))
g_value_set_long(&value, PyLong_AsLong(obj));
break;

case G_TYPE_UINT:
if (PyLong_Check(obj))
g_value_set_uint(&value, PyLong_AsUnsignedLong(obj));
break;

case G_TYPE_ULONG:
if (PyLong_Check(obj))
g_value_set_ulong(&value, PyLong_AsUnsignedLong(obj));
break;

case G_TYPE_FLOAT:
if (PyFloat_Check(obj))
g_value_set_float(&value, PyFloat_AsDouble(obj));
break;

case G_TYPE_DOUBLE:
if (PyFloat_Check(obj))
g_value_set_double(&value, PyFloat_AsDouble(obj));
break;

default:
if (PyString_Check(obj))
g_value_set_string(&value, PyString_AsString(obj));
break;
}
gtk_list_store_set_value(GTK_LIST_STORE(model), &iter, i, &value);
}

//Py_XDECREF(args);
return FALSE;
}

void
etc_main_win_add_trans(PyObject *args)
{
//Py_INCREF(args);
g_idle_add(_etc_main_win_add_trans, args);
}

没有评论: