背景:
一個包含了組件提升的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"
...
而主ui和子ui中都有一樣名字的按鈕pushButton1,所以my_ui.h和my_sub_ui.h中也一樣會有兩個槽函數的聲明on_pushButton1_clicked。編譯器咋整?如果按照名字匹配信號槽,效果跟connect是一樣的,但又不完全一樣,主界面中的槽函數等于被覆蓋了,所以有效的永遠是子ui中的槽函數。
亂七八糟的不知道說明白了沒有。畢竟qt按照名字on_XXX_signal匹配信號槽的做法,跟connect還是有區別,這個感興趣可以分析源碼。
結論:
所以,如果有ui嵌套,控件命名一定不能重復。
?