信号:
* 信号必学用signals关键字来声明,signals是Qt拓展的关键字
* 信号没有返回值,但可以有参数
* 信号就是函数声明,只需声明,无需定义
* 使用: emit mySignal();
* 信号可以重载
使用connec进行从指定类型将信号发送给接受对象的方法的链接,例如:
connect(&b1,&QPushButton::pressed,this,&MyWidget::close); /*参数: * &b1:信号发出者,指针类型 * &QPushButton:pressed:处理的信号,&发送者的类名::信号名字 * this:信号接受者 * &MyWidget::close:槽函数,即信号处理函数,&接受的类名::槽函数 */
自定义槽函数:
* Qt5:任意成员函数,普通全局函数,静态函数
* 槽函数需要和信号一致(参数,返回值)
* 由于信号没有返回值,所以,槽函数一定没有返回值,例如:
connect(&b2,&QPushButton::released,this,&MyWidget::mySlot); //槽函数 void MyWidget::mySlot() { //b2是一个QPushButton类型 b2.setText("123"); }
无参数信号:
例如:
//定义一个信号 signals: void mySignal(); //使用信号 void SubWidget::sendSlot() { emit mySignal(); }
信号和槽函数使用示例:
功能:切换窗口,并隐藏当前窗口
主窗口
class MyWidget : public QWidget { Q_OBJECT public: MyWidget(QWidget *parent = 0); void mySlot(); void changeWin(); void dealSub(void); ~MyWidget(); private: QPushButton b1; //窗口关闭按钮 QPushButton b3; //切换窗口按钮 SubWidget w; //另一独立窗口 };
方法实现:
MyWidget::MyWidget(QWidget *parent) : QWidget(parent),b1(this) { b1.setText("close"); b1.move(100,100); connect(&b1,&QPushButton::pressed,this,&MyWidget::close); setWindowTitle("老大");//设置窗口标题 b3.setParent(this); //绑定父对象 b3.setText("切换到子窗口"); b3.move(50,50); connect(&b3,&QPushButton::released,this,&MyWidget::changeWin); connect(&w,&SubWidget::mySignal,this,&MyWidget::dealSub); } void MyWidget::dealSub() { w.hide(); this->show(); } void MyWidget::changeWin() { w.show(); this->hide(); } MyWidget::~MyWidget(){}
第二个窗口:
class SubWidget : public QWidget { Q_OBJECT public: explicit SubWidget(QWidget *parent = nullptr); void sendSlot();//槽函数 signals: void mySignal(); public slots: private: QPushButton b1;//切换窗口按钮 };
方法实现:
SubWidget::SubWidget(QWidget *parent) : QWidget(parent) { this->setWindowTitle("小弟"); b1.setParent(this); b1.setText("切换到主窗口"); //当按键按下时产生信号,调用sendSlot发送信号mySignal() connect(&b1,&QPushButton::clicked,this,&SubWidget::sendSlot); } void SubWidget::sendSlot() { emit mySignal(); }
有参数的信号:
信号重载后,会照成二义性问题,信号和槽函数必须一制,即参数列表类型和顺序一样,但参数个数可以不一样(Ps:信号的参数个数大于等于槽函数参数个数,反之不可)。
信号:
void mySignal(int,QString);
emit mySignal(250,"我是子窗口");
槽函数:
void MyWidget::dealSlot(int a,QString str) { //str.toUtf8()转换成字节数组QByteArray //.............data() 转换成char* qDebug() << a << str.toUtf8().data(); }
解决方法如下:
1.通过不同的函数指针,区分接收到的信号
void (SubWidget::*funSignal)() = &SubWidget::mySignal; void (SubWidget::*testSignal)(int,QString) = &SubWidget::mySignal; connect(&w,funSignal,this,&MyWidget::dealSub); connect(&w,testSignal,this,&MyWidget::dealSlot);
2.使用Qt4中的方法:
* Qt4槽函数必须有slots关键字修饰
* 缺陷:SIGNAL SLOT 将函数名字转换成字符串,不进行错误检查
* 建议:使用Qt5的处理方法
类中定义:
...... public slots: void mySlot(); void changeWin(); void dealSub(); void dealSlot(int,QString); ......
函数实现中应用:
...... connect(&w,SIGNAL(mySignal(int,QString)),this,SLOT(dealSlot(int,QString))); connect(&w,SIGNAL(mySignal()),this,SLOT(dealSub())); ......
Lambda表达式:匿名函数对象
* C++11新增加的特性,配合信号使用,非常方便
* 需要在项目文件添加:CONFIG += C++11
QPushButton *b4 = new QPushButton(this); b4->setText("Lambda表达式"); b4->move(150,150); int a=10,b=100; /* * []用来传递外部参数, * = :把外部所有局部变量,类中所有成员以值传递方式,但是是只读的,使用mutable改变, * this:类中所有成员以值传递方式 * & :把外部所有局部变量以值传递方式,避免使用 * () :接受到的参数 */ connect(b4,&QPushButton::clicked, [=](bool isCheck)mutable { qDebug() << "111111"; qDebug() << a << b; qDebug() << isCheck; a = 11; } );
*是在上面示例程序中的信号(我自己理解的,如有错误,还请指出)
released():当按键释放时产生
pressed() :当按键按下时产生
clicked(bool checked = false) :当按键被激活时产生(按钮被按下,然后释放)