和大家探讨一下Glade3生成的界面在C里无法正确使用user_data问题的解决方法

软件和网站开发以及相关技术探讨
回复
schun
帖子: 2
注册时间: 2009-08-10 23:38

和大家探讨一下Glade3生成的界面在C里无法正确使用user_data问题的解决方法

#1

帖子 schun » 2009-08-11 0:28

Glade3不再能生成C或C++或其他什么代码了,现在改为使用libglade在程序运行时加载并解析glade文件中的XML文档来生成界面了,这种做法倒是更符合界面设计同程序设计分离的理念,事实上当界面稍复杂一点后,在面对Glade2生成的一大堆C代码时也是比较头痛的事情,个人认为Glade3的模式应该更合理一些。
不过目前Glade3似乎在C上有BUG,别的语言没试过(主要是除了C不懂别的了 :em04 ),在Glade3的属性面板里定义的信号处理函数无法接收到正确的参数,具体表现为:
如果在Glade3中定义了处理函数:
void on_button1_clicked (GtkButton *self, gpointer user_data)
则实际运行中self = NULL, user_data = self
对此我的解决是。。。。,还是看代码算了 :em06

void on_button1_clicked (GtkButton *self, gpointer user_data);

// 准备传递的user_data数据结构
static struct U_Data {
int mal;
char str[100];
} button1_user_data = {0, "应用程序数据在此"};

// 定义一个简短的调用缩写,使用一个信号连接可在一行内写完,以便构建表格式连接代码块!写成宏也可,但是用函数可使编译器能更准确的定位语法错误
// SGC这个名字可能有些欠考虑,感觉和某些系统中定义的常量相近但含义相远吧
inline void SGC(GladeXML *gxml, const char *widget_name, const char *signal, void *func, gpointer user_date) {
g_signal_connect(
GTK_OBJECT(glade_xml_get_widget(gxml, widget_name)),
signal,
GTK_SIGNAL_FUNC(func),
user_date);
}

GtkWidget* create_window (void) {
GtkWidget *window;
GladeXML *gxml;

gxml = glade_xml_new (GLADE_FILE, NULL, NULL);

/* This is important */
glade_xml_signal_autoconnect (gxml);
window = glade_xml_get_widget (gxml, "window");

// 连接需要使用self, user_data的函数,因为目前Glade无法正确处理他们
SGC(gxml, "button1", "clicked", on_button1_clicked, &button1_user_data);
/* 如果不用SGC宏(函数)则以上调用将不适合写在一行内(见下),写在一行会很长,不便阅读。当然一个窗口中要连接的这种信号较多时
简单的写法应该会更易阅读和对大量信号连接的集中维护。
gtk_signal_connect(
GTK_OBJECT(glade_xml_get_widget(gxml, "button1")),
"clicked",
GTK_SIGNAL_FUNC(on_button1_clicked),
&button1_user_data);
*/

return window;
}

int main (int argc, char *argv[]) {
GtkWidget *window;

puts(argv[0]);

#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#endif

gtk_set_locale ();
gtk_init (&argc, &argv);

window = create_window ();
gtk_widget_show (window);

gtk_main ();
return 0;
}

void on_button1_clicked (GtkButton *self, gpointer user_data) {
struct U_Data* data = (struct U_Data *)user_data;
data->mal ++;
printf("Button click (%d),信息:%s\n", data->mal, data->str);
}
以上做法经试验可行,不过这属于穿Glade3这个新鞋走老路的干法。不知道大家在解决这个问题时有何更好的办法,欢迎共同探讨(砖头是丢出去了,大家给来点玉吧)。
至于不用Glade3而继续用Glade2这个办法就请不要说了 :em20,如果谁有解决Glade3中这个BUG的补丁就更好了,请发个上来大家共享下吧 :em02
头像
qingshi163
帖子: 275
注册时间: 2007-12-16 0:45

Re: 和大家探讨一下Glade3生成的界面在C里无法正确使用user_data问题的解决方法

#2

帖子 qingshi163 » 2009-08-11 5:41

我真没这个问题阿,glade3,2都是好的。难道运行时没抛出错误或警告?

你那个SGC没必要吧,在glade中将信号设置上,然后 glade_xml_signal_connect[_data] 这两个函数连接一下就可以了阿。而且我看你用了autoconnect的,那么只要函数名和信号一样都不用手动去连接了
schun
帖子: 2
注册时间: 2009-08-10 23:38

Re: 和大家探讨一下Glade3生成的界面在C里无法正确使用user_data问题的解决方法

#3

帖子 schun » 2009-08-11 9:25

qingshi163 写了:我真没这个问题阿,glade3,2都是好的。难道运行时没抛出错误或警告?

你那个SGC没必要吧,在glade中将信号设置上,然后 glade_xml_signal_connect[_data] 这两个函数连接一下就可以了阿。而且我看你用了autoconnect的,那么只要函数名和信号一样都不用手动去连接了
在glade中设置信号,同时设置了用户数据后,运行时self和user_data就是不正常,运行也没有出现错误或警告,实际上如果不在信号处理中用断点停下来观察的话,后面使用user_data的代码将会出现段错误导致程序终止,因为这时user_data实际上的值是self的值,而self=NULL,也就是说autoconnect虽然建立了处理函数的连接,即在运行时确能根据信号去调用设定的处理函数,但是在参数的传递上确有问题,是不是我在glade中设置的方式不对呢?在glade的属性面板中设置要传给函数的数据如上面的代码中的button1_user_data时应该如果填写请再帮看看.使用手动连接实为无奈之举,如果在glade中能解决我认为不应该在程序中再用手动连接,除非是有些处理需根据程序运行来动态改变处理函数的情况。
用SGC宏的主要是为了简化一点代码的长度,毕竟手动连接的话要连接的函数会较多,能把每个连接都写的一行内还是有些好处的(实际上也可不用,这只是个各人代码风格的问题),只是上面SGC的内部用的是g_signal_connect的确不如用glade_xml_signal_connect_data好。
能不能发一下你在glade设置了user_data后能正常接收user_data的glade文件中的相应代码片段和程序中的对应片段,以便我对比一下和我的glade文件中的差别,现在看来我的glade中的设置可能是有问题的,毕竟glade的中文文档目前好象没有,我的英文相当于现在的小学水平 :em06 ,无奈。
leisure
帖子: 141
注册时间: 2008-05-03 16:43
联系:

Re: 和大家探讨一下Glade3生成的界面在C里无法正确使用user_data问题的解决方法

#4

帖子 leisure » 2009-12-07 23:42

schun 写了:
qingshi163 写了:我真没这个问题阿,glade3,2都是好的。难道运行时没抛出错误或警告?

你那个SGC没必要吧,在glade中将信号设置上,然后 glade_xml_signal_connect[_data] 这两个函数连接一下就可以了阿。而且我看你用了autoconnect的,那么只要函数名和信号一样都不用手动去连接了
在glade中设置信号,同时设置了用户数据后,运行时self和user_data就是不正常,运行也没有出现错误或警告,实际上如果不在信号处理中用断点停下来观察的话,后面使用user_data的代码将会出现段错误导致程序终止,因为这时user_data实际上的值是self的值,而self=NULL,也就是说autoconnect虽然建立了处理函数的连接,即在运行时确能根据信号去调用设定的处理函数,但是在参数的传递上确有问题,是不是我在glade中设置的方式不对呢?在glade的属性面板中设置要传给函数的数据如上面的代码中的button1_user_data时应该如果填写请再帮看看.使用手动连接实为无奈之举,如果在glade中能解决我认为不应该在程序中再用手动连接,除非是有些处理需根据程序运行来动态改变处理函数的情况。
用SGC宏的主要是为了简化一点代码的长度,毕竟手动连接的话要连接的函数会较多,能把每个连接都写的一行内还是有些好处的(实际上也可不用,这只是个各人代码风格的问题),只是上面SGC的内部用的是g_signal_connect的确不如用glade_xml_signal_connect_data好。
能不能发一下你在glade设置了user_data后能正常接收user_data的glade文件中的相应代码片段和程序中的对应片段,以便我对比一下和我的glade文件中的差别,现在看来我的glade中的设置可能是有问题的,毕竟glade的中文文档目前好象没有,我的英文相当于现在的小学水平 :em06 ,无奈。
这个问题确实存在,我使用gtk_builder来解析的Glade生成的xml,选择的格式就是默认的GtkBuilder而不是libGlade。
gracegreen
帖子: 48
注册时间: 2009-03-27 14:34

Re: 和大家探讨一下Glade3生成的界面在C里无法正确使用user_data问题的解决方法

#5

帖子 gracegreen » 2010-03-25 9:58

因为gtkbuilder一旦在xml里指定用户数据,就会使用g_signal_connect_swap()的方式来连接,所以交换了参数的顺序!
luqing520
帖子: 7
注册时间: 2011-12-10 18:11

Re: 和大家探讨一下Glade3生成的界面在C里无法正确使用user_data问题的解决方法

#6

帖子 luqing520 » 2012-02-22 22:19

how to build a c code?
回复