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关闭窗口

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QT 5.12版本中信号的使用方式有所改变。在以前的版本中,我们可以使用connect函数来连接信号,例如connect(sender, SIGNAL(signal()), receiver, SLOT(slot()))。但在QT 5.12版本中,SIGNAL和SLOT宏已经不再需要使用了。 在QT 5.12版本中,我们可以使用新的语法直接连接信号。例如,如果我们有一个按钮m_applyBtn,并且想在按钮按下时执行一个函数onApplyBtnPressedSlt,我们可以这样做: ```cpp connect(m_applyBtn, &QPushButton::pressed, this, &MyClass::onApplyBtnPressedSlt); ``` 这里,&QPushButton::pressed表示按钮按下的信号,this表示接收信号的对象(一般是当前类的实例),&MyClass::onApplyBtnPressedSlt表示要执行的函数。 同样地,如果我们有另一个按钮m_backBtn,并且想在按钮按下时执行另一个函数onBackBtnPressedSlt,我们可以使用以下代码进行连接: ```cpp connect(m_backBtn, &QPushButton::pressed, this, &MyClass::onBackBtnPressedSlt); ``` 这样,按钮的pressed信号就会触发相应的函数。 需要注意的是,在新的语法中,信号的参数类型必须一致。如果信号的参数不一致,可以使用QOverload和QMetaObject::Connection来解决这个问题。但这超出了本次讨论的范围。 总结起来,QT 5.12版本中,我们可以使用新的语法直接连接信号,不再需要使用SIGNAL和SLOT宏。使用新的语法可以提供更好的类型安全性和编译时错误检查。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [QT5.12中的信号问题](https://blog.csdn.net/bxlover007/article/details/116204430)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [QT C++学习代码案例](https://download.csdn.net/download/m0_73878864/88259441)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值