信号与槽
简介
简介没有,网上一搜一大把,就不写了
用法
用法也没有,网上也很多
注意事项
1、自己创建对象,里面有信号与槽,需要继承QObject类
2、创建用槽连接信号,信号和槽的参数要对应。
要将信号与槽链接成功,在有参数的情况下,以下几种情况下都可以链接信号槽成功:
- 信号的参数个数与类型与对应的槽函数参数的个数与类型一致
- 信号的参数个数多于对应的槽函数的参数个数,即对应的槽函数的参数个
数可以比信号函数少,但槽函数的所有参数类型必须与信号的参数类型保持一致
- 槽函数与信号函数有默认参数的情况时,遵循以上的第二种规律。
- 综上,信号与槽想要链接成功,则槽函数有的参数个数和类型,在对应的信号函数中必须一一对应,但信号函数的参数个数一定多于或等于槽函数的参数个数
3、避免多次连接
同一信号与槽可以连接多次,多链接一次,在触发信号时,就会多执行一次槽。
比如下面的例子;
for(int i = 0;i<ui->listWidget->count();i++){
qDebug()<<ui->listWidget->item(i)->text();
ftpconnect.ftpPut(ui->listWidget->item(i)->text());
connect(&ftpconnect, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
}
这是获取列表中的文件地址,然后将文件上传到ftp服务器中的代码。原意是上传多个文件,然后将报错的信号与槽连接起来,有多少个文件,就有多少个槽。执行后就会发现,若有多个文件,第一个文件上传出错,error方法执行一次,第二个文件上传,error方法执行两次,第三个文件上传error方法就会执行三次。。。。。。越来越多。
解决办法,在for循环前连接一次就行,或者,在for循环里面先disconnect,再connect。
4、在槽函数中获取发出信号的对象
核心方法:QObject::sender()
对于信号与槽的连接
connect( obj1 , SIGNAL(sigFun()) , obj2 , SLOT(slotFun()) )
或者
connect( obj1 , &Object1::sigFun , obj2 , &Object2::slotFun )
可以通过信号与槽函数的参数来传递数据
但是有时候我们希望能在slotFun()里去获得obj1对象指针,那么我们就可以用Qt基类QObject::sender(),在槽函数里获得绑定的信号的来源对象,解决一些动态绑定信号与槽的情况。
QCheckBox* checkBox= new QCheckBox(ui->widget_2);
QString text="" ;
//do something
checkBox->setText(text);
checkBox->setChecked(true);
connect(checkBox,SIGNAL(clicked(bool)),this,SLOT(checkBoxClick(bool)));
如上所示,这段代码可能调用好多次,但所有的信号都是用一个槽处理,当我们需要知道发出信号的对象的一些信息的时候,就需要使用QObject::sender()
tmpQCheckBox = (QCheckBox*) sender();
//do something
但发送信号的对象是不同的类时,但处理的是同一个槽是,我们就要做一些处理了,如:
QPushButton* button= new QPushButton(ui->widget_2);
QString text="" ;
//do something
button->setText(text);
connect(button,SIGNAL(clicked()),this,SLOT(checkBoxClick()));
两个信号都连接到了一个槽,我们就需要在槽中把这些信号的发送者都识别出来,然后取其相应的键值然后发送,其方法是:
if (QPushButton* btn = dynamic_cast<QPushButton*>(sender())){
//dosomething
}
else if (QCheckBox *check = dynamic_cast<QCheckBox*>(sender())){
//do something
}
在槽(SLOT)中sender()函数会返回一个指向QObject 的指针来指向信号的发送者(Returns a pointer to the object that sent the signal, if called in a slot activated by a signal;)。然后通过C++ RTTI(Run-Time Type Identification)机制提供的dynamic_cast运算符,在执行的时候检查sender()返回的对象是否是QPushButton类,如果是则将sender()返回的QObject指针转换为QPushButton指针,然后if中的语句就会执行。如果sender()返回的对象不是QPushButton类型的指针,则dynamic_cast就会返回0,if中的语句就不会执行了。
致自己:
给自己定一个五年的目标,然后,把它分解成一年一年,半年半年的,三个月的,一个月的。这样,你才能找到自己的目标和方向。那么先来一个小目标,这个月coding 1万行。