QT学习-2 <信号和槽>

 ——  均为自学笔记,如有错误请指正


第一节  信号和槽


一、点击按钮关闭窗口

1. 介绍  连接函数connect()

按钮——点击——窗口——关闭窗口

connect(信号的发送者,发送的具体信号,信号的接收者,信号的处理(槽)) 

  • 槽就是信号处理的槽函数
  • 信号槽的优点:松散耦合(信号发送端和接收端本身是没有关联 的,通过connect连接,将两端耦合在一起)

2. 使用 connect()

connect(发送者(指针/地址),发送的信号(函数的地址),接收者(指针/地址),处理的槽(函数地址))

connect(myBtn,&QPushButton::clicked,this,&QWidget::close); //父类
// or
connect(myBtn,&MyPushButton::clicked,this,&myWidget::close);//子类

注: 对于函数来说,函数名可以隐式转换为函数指针,因此&写与不写一致。

3. 信号Signals :
  • void clicked(bool checked = false)  点击
  • void pressed()   摁下瞬间
  • void released()  释放瞬间
  • void toggled(bool checked)          根据bool切换状态            //toggled:切换
4. 槽函数(Qt助手可查看 QWidget → Public Slots)


二、创建自定义的信号和槽

案例需求:

        //Teacher 类 老师类
        //Student 类 学生类
        //下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭

分析:发送者:Teacher  ,信号 :饿了,接收者:学生,处理槽函数:请吃饭

1.  新建

当新建的类不属于任何一个控件时,可以选择最高级别的类,如下图:

2. 自定义信号

①  位置:创建好类以后在  类.h  文件中的signals 下就是写自定义信号的位置,如下图:

② 写法:

  • 没有返回值,即返回值是void ,在信号里面只需要声明,不需要实现
  • 可以有参数,可以无参数,即可以重载
 3. 自定义槽函数

① 位置:写在  接收类.h  文件的 public下

注:早期版本必须写在public slots下,高级版本可以写在public或者全局下

② 写法:

  • 返回值 void,需要声明,也需要实现
  • 可以有参数,可以发生重载
4. 声明对象

位置 :在   widget.h  中声明对象

    Teacher  * zt;
    Student *  st;
5. 创建对象

位置 : 在  widget.cpp  中创建对象

    //创建一个老师对象
    this->zt = new Teacher(this);

    //创建一个学生对象
    this->st = new Student(this);
 6. 连接

位置 : .cpp中 创建完对象后

写法:connect();

7. 方法(条件)

注: 下课后这个   条件(方法)

① 写法:需声明,需实现。

② 声明位置: widget.h下

void classIsOver();

③ 实现位置: widget.cpp下

void Widget::classIsOver()
{
    //下课函数,调用后,触发老师饿了的信号
    emit zt->hungry();
}

注: 调用  信号 (发送者那个信号)

触发自定义的信号:emit  自定义信号

④ 调用方法:widget.cpp下

//调用下课函数
classIsOver();

注: 注意调用方法和信号的代码顺序

三、自定义的信号和槽  出现重载

注:成员函数和指向该成员的指针之间不存在自动转换规则,所以必须显式地使用取址运算符(&)

  • 需要利用函数指针 明确指向函数的地址
//声明成员函数的函数地址时,需在指针前边加成员函数的作用域

void( Teacher:: *teacherSignal)(QString) = &Teacher::hungry; 

void(Student:: *stuentSlot)(QString) = &Student::treat;

connect(zt,teacherSignal,st,stuentSlot);

classIsOver();
  • QString 格式 转成 char*
//QString型打印出来会加"",转换一下即可取消

//QString -> char* 转换:
//先转成QByteArray :    通过 .toUtf8()
//转成char* :       通过 .data() 


qDebug()<<  "eat _this" << foodName.toUtf8().data() ;

四、 信号连接与断开

1. 信号连接信号  信号连接槽  断开信号

    //点击按钮  触发下课事件

    // 信号连接槽
    connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);

    //无参的信号和槽连接
    void(Teacher:: *teacherSignal2)(void) = &Teacher::hungry;
    void(Student:: *studentSlot2)(void) = &Student::treat;
    connect(zt,teacherSignal2,st,studentSlot2);

    //信号连接信号
     connect(btn,&QPushButton::clicked,zt,teacherSignal2);

     //断开信号
    disconnect(zt,teacherSignal2,st,studentSlot2);
2. 信号连接拓展:
  • 信号可以连接信号
  • 一个信号可以连接多个槽函数
  • 多个信号可以连接同一个槽函数
  • 信号和槽函数的参数类型必须一一对应
  • 信号和槽的参数个数 是不是要一致? 信号的参数个数可以多于槽函数的参数个数(但是对应的类型需要一致)
3. Qt4版本以前的信号和槽连接方式
//Qt4 连接无参版本

connect(zt,SIGNAL(hungry()),st,SLOT(treat()));

//优点: 参数直观。缺点: 类型不做检测。

// 错误例子:connect(zt,SIGNAL(hungry()),st,SLOT(treat(QString)));



Qt4版本  底层:SIGNAL("hungry")   SLOT("treat") 字符串直接找函数

五、Lambada表达式(C++11新特性)

1. 简介

用于定义并创建匿名的函数对象

2. 基本构成
/*
[函数对象参数](操作符重载函数参数)mutable->返回值
{
    函数体
}
*/
[capture](parameters)mutable->return-type
{
    statement
}


//将btn按钮改名   最后的 ();是函数调用,不调用无法成功。
[=]()
{
    btn->setText("aaa");
}();
3. 配置

早期版本需要在.pro中加入 CONFIG += c++11

4. 函数对象参数形式   [ ]

空:没有使用任何函数对象参数

= :函数体内可以使用Lambda所在作用范围内所有可见的局部变量(值传递方式)

&:函数体内可以使用Lambda所在作用范围内所有可见的局部变量(引用传递方式)

this:函数体内可以使用Lambda所在类中的成员变量

a :将a按值进行传递。修改需加mutable修饰符

&a:将a按引用进行传递

a,&b:将a按值进行传递,b按引用进行传递

=,&a,&b:除了a和b按引用进行传递外,其他参数都按值进行传递

&,a,b:除a,b按值传递,其他参数都按引用进行传递

5. 操作符重载函数参数   ( )

标识重载 ( ) 操作符的参数,没有参数时,这部分可以省略。参数可以通过按值(a,b)和按引用(&a,&b)进行传递。

6. 可修改标示符

mutable声明,这部分可以省略。

按值传递函数对象参数时,加上mutable修饰符(      在 [ ] ( ) 这里添加{ }     )后,可以修改按值传递进来的拷贝(只能是拷贝,不能是本身)。

QPushButton * myBtn = new QPushBtoon(this);

QPushButton * myBtn2 = new QPushBtoon(this);

myBtn->move(100,100);

int m = 10;

connect(myBtn,&QPushButton::clicked,this,[m]()mutable{m = 100+10;qDebug()<<m;});

connect(myBtn2,&QPushButton::clicked,this,[=](){qDebug()<<m;});

qDebug()<<m;
7. 函数返回值

->返回值类型,标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方时,这部分可以省略。

int ret = []()->int{return 1000;}();  //此处的()是调用函数,必须得有

qDebug() << "ret = "<< ret;
8. 函数体   { }

标识函数的实现,这部分不能省略,但函数体可以为空。

9.  使用
  • 点击按钮关闭窗口
  • connect() 第三个参数是this时,可以省略
QPushButton * btn2 = new QPushButton;
btn2->setText("close");
btn2->move(100,0);
btn2->setParent(this);


// 下面第三个参数是this时可以省略
connect(btn2,&QPushButton::clicked,this,[=]()
{


    this->close();

    //此处可以直接调用槽函数
    emit zt->hungry("foodName");

});
10. Lambda表达式最常用: [=](){}

六、作业

1. 普通版:

创建两个按钮:一个open,另一个close,点击open,弹出另一个窗口,点击close关闭所打开的窗口

2. 升级版:

一个按钮,显示open,点击打开窗口,并且显示为close,点击close关闭窗口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值