背景:
一个包含了组件提升的ui,有个按钮的槽函数就是不响应,于是找原因。
分析:
槽函数的对应一是通过connect函数绑定信号,二是on_XXX_signal的命名方式。界面上部件的槽函数通常是第二种。
我反复确认细节,就是找不到问题。知道跟踪moc文件,发现qt_static_metacall函数都不执行。
之前还写过一篇博客:
qt槽函数重写问题,qt_metacall和qt_static_metacall-CSDN博客
为了测试原因,我几乎点了界面上所有的按钮,其它都可以执行qt_static_metacall,直到发现一个低级原因:界面上如果用嵌套方式,里面又套了一层widget,并让它提升为另一个自定义的界面,其中有个按钮的名称和外面的重复,这就不行了。比如:
原因:
如图所示:一个主ui中嵌套了一个子ui,子ui里面有个pushButton1,主ui里也有一个,这样就不行。按理说,这就好比函数或者模块化设计,分离开来就是怕乱,但是不行,分离开也要注意命名。
在cpp的构造函数中,通常有个setupUi函数,而它存在于ui_XXX.h当中,这就是原因。
主ui的cpp的ui_头文件中,一定会有子ui的ui_头文件。正如我的ui里放了个按钮,那么它的ui_头文件里一定会有#include <QPushButton>。要不构造的时候调用setupUi,怎么生成这个按钮?
所以,放眼主ui的cpp文件,开头一定是:
#include "my_ui.h"
#include "ui_my_ui.h"
按上图的意思,ui_头文件当中展开,成了:
#include "my_ui.h"
...
#include "my_sub_ui.h"
#include "ui_my_sub_ui.h"
...
而主ui和子ui中都有一样名字的按钮pushButton1,所以my_ui.h和my_sub_ui.h中也一样会有两个槽函数的声明on_pushButton1_clicked。编译器咋整?如果按照名字匹配信号槽,效果跟connect是一样的,但又不完全一样,主界面中的槽函数等于被覆盖了,所以有效的永远是子ui中的槽函数。
乱七八糟的不知道说明白了没有。毕竟qt按照名字on_XXX_signal匹配信号槽的做法,跟connect还是有区别,这个感兴趣可以分析源码。
结论:
所以,如果有ui嵌套,控件命名一定不能重复。