Qt5------信号和槽函数

信号:

  * 信号必学用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) :当按键被激活时产生(按钮被按下,然后释放)

原文地址:https://www.cnblogs.com/zhangzeze/p/9134033.html