转:http://hi.baidu.com/passion_wu128/item/ac39f69733e591d41b49df50
今天写代码中发现按照 void on_<object name>_<signal name>(<signal parameters>) 规则命名的槽函数不起作用,而且提示:QMetaObject::connectSlotsByName: No matching signal for on_btn_test_clicked(),简略代码如下:
class EventDemo : public QWidget{
Q_OBJECT
public:
EventDemo(QWidget *parent = 0);
virtual ~EventDemo(){}
private:
QPushButton *btn_test;
public slots:
void on_btn_test_clicked();
};
EventDemo
::EventDemo
(QWidget *parent)
: QWidget(parent)
{
QPushButton *btn_test = new QPushButton(this);
btn_test->setText("test");
}
void EventDemo::on_btn_clicked()
{
qDebug () << Q_FUNC_INFO;
}
运行后点击 test 按钮并没有打印出函数信息。
然后想起以前Qt生成的ui_name.h文件里面有这个函数:
connectSlotsByName
于是在类EventDemo的开头开头加上:QMetaObject::connectSlotsByName ( * object );
connectSlotsByName是这样描述的:
Searches recursively for all child objects of the given object , and connects matching signals from them to slots of object that follow the following form:void on_<object name>_<signal name>(<signal parameters>);
意思就是会遍历此类的所有子对象,然后找到object name和槽函数中匹配的object name,再连接信号和槽。
所以如果将
connectSlotsByName函数放在构造函数开头当然不行,因为这个函数运行时,btn_test并不是此类的子对 象!!!
connectSlotsByName放在构造函数末尾,但还是不行,郁闷……
再调试进入
connectSlotsByName函数(函数有点长就不贴了),发现并没有找到object name为btn_test的子对象,于是写一段代码测试之:
const QObjectList list = this->children();
qDebug() << list.count();
for(int j = 0; j < list.count(); ++j) {
const QObject *obj = list.at(j);
qDebug() << obj->objectName();
}
输出的调试信息显示list的count()值为1,但是objectName却为 “”
于是想到另一个函数setObjectName
再添加一行代码:
btn_test->setObjectName("btn");
终于搞定……
总结:
1,如果没有用UI生成的文件而又想按上述规则命名槽函数来实现信号和槽的连接的话,需要调用
void QMetaObject::connectSlotsByName ( * object ) 函数,而且必须在发送信号的对象成为object的子对像之后调用。
2,变量名和objectName不是同一个概念(以前一直以为相同,汗~),所以需要显式设置objectName;
(百度空间,糟糕的排版~,尤其是代码!)
2532





