在创建QT的信号和槽时,经常无意间保留着QT书写槽函数的习惯,或者在QT设计界面直接右键【转到槽】去创建槽函数,但是后期需要用到disconnect时,又重新写了一遍connect函数,那么你会发现实际槽函数执行了2遍。
首先来看下这种QT的槽函数书写习惯:void on__();
例如,我创建了一个lineEdit,并且给这个控件的oeject name命名为lineEdit,那么这个lineEdit的textChanged信号对应的默认槽函数就是:
void on_lineEdit_textChanged(QString text);
那么这种命名方式有什么问题呢?首先看下这个代码:
void MainWindow::on_lineEdit_textChanged(QString text)
{
count ++;//一个自增的int值
qDebug() << count;
ui->label->setText(text);//一个label来显示text变化
}
很明显这个命名规则是符合QT命名规则的,那么我们此时不去创建connect,仅仅去emit一个signal会发生什么呢?
emit ui->lineEdit->textChanged("test");
可以明显看到label的test发生了变化。
我们再做一个实验,新增一个connect去试下槽函数执行了几次:
connect(ui->lineEdit, &QLineEdit::textChanged, this, &MainWindow::on_lineEdit_textChanged);
可以看到实际槽函数执行了2遍,这就不符合我们的实际需求了。
我们来看下为什么呢?点击进去ui_文件中,你可以看到这一句函数:
QMetaObject::connectSlotsByName(MainWindow);
QT对此做了解释:
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_();
Let’s assume our object has a child object of type QPushButton with the object name button1. The slot to catch the button’s clicked() signal would be:
void on_button1_clicked();
递归搜索给定对象的所有子对象,并将来自这些子对象的匹配信号连接到遵循以下形式的对象槽
可以看到QT会去搜索所有的对象,并且把这些子对象的信号连接到符合void on_()形式的槽函数上,并且这种连接是自动的!!!!
难怪我们自己connect以后,槽函数会执行2遍,因为QT帮助我们自动connect了一次。
为了避免这种方式的错误,那么我们最好在写槽函数的时候,不要遵守QT的槽函数明明方式,最简单的就是不要加on_;或者如果想用QT自带的信号槽,那就不要多于的去connect。