connect()函数的5种用法:
第一种
Qt 4 使用宏,主要通过connect + 宏的方式进行通信连接。
connect(发送对象,信号,接收对象,槽函数),其中发送信号和槽函数需要用 SIGNAL() 和 SLOT() 来进行明确的声明。
以下示例先自定义一个 Button,然后定义两个信号:
class MyButton : public QWidget
{
Q_OBJECT
public:
explicit MyButton(QWidget *parent = nullptr);
signals:
void sigClicked();
void sigClicked(bool check); //重载信号
};
那么在用这个 Button 的时候连接这两个信号,按照旧版本的写法,应该是这样:
connect(m_pBtn,SIGNAL(sigClicked()),this,SLOT(onClicked()));
connect(m_pBtn,SIGNAL(sigClicked(bool)),this,SLOT(onClicked(bool)));
这种写法比较麻烦,常常在用的时候缺少括号,不过该写法很明确,一眼就能看出来是将哪个信号连接到哪个槽。
第二种
Qt 5 推出了新的 connect 函数,不需要使用 SIGNAL() 和 SLOT() 宏,可以在编译时做类型检查:
connect函数原型如下:
[static] QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)
用 connect 将信号与槽函数连接,不需要再使用 SIGNAL() 和 SLOT() 宏:
connect(m_pBtn,&MyButton::sigClicked,this,&Widget::onClicked);
这种写法看起来很简洁,但是存在一些坑需要注意,这句写法如果用在上面的示例中,会报错下面的错误:
error: no matching member function for call to 'connect' connect(m_pBtn,&MyButton::sigClicked,this,&Widget::onClicked);
这是因为我们自定义的 Button 中存在两个重载信号,然后用这种 connect 的方式会无法识别到底想要连接哪个信号。所以,如果信号是重载的话,需要用下面的写法来替换:
connect(m_pBtn, static_cast<void (MyButton::*)(bool)>(&MyButton::sigClicked), this, &Widget::onClicked);
问题又来了,如果我的onClicked槽也是重载的话,还是会报同样的错误。因为编译器不知道你想要真正连接哪个槽。所以这里建议,如果信号重载,可以用上面的方法来写,如果槽重载…还是用第一种方法来 connect 吧,比较保险,虽然比较麻烦点。
第三种
最后来看一种最新的写法,忘记是在 Qt 的哪个版本推出的了,主要针对重载信号的连接做了调整,会更简单些:
同样是上面的示例:
connect(m_pBtn, QOverload<bool>::of(&MyButton::sigClicked),this,&Widget::onClicked);
很显然这种写法相对于第二种会比较简单些,但依然不能连接到重载的槽函数,如果连接重载槽函数,还是会报之前的错误。
第四种:Lambda 函数写法
个人比较喜欢用lambda函数的方式,如果槽函数中的内容比较简单的话,没必要再去单独定义一个槽来连接, 直接用Lambda 函数会更简单。
来看一下示例:
connect(m_pBtn, QOverload<bool>::of(&MyButton::sigClicked), this, [=](bool check){
qDebug() << "do something";
});
connect(m_pBtn, static_cast<void (MyButton::*)(bool)>(&MyButton::sigClicked), this, [=](bool check){
qDebug() << "do something";
});
connect(ui->lineEdit, &QLineEdit::textEdited, this, [=](QString s){
qDebug() << s;
});