Qt6学习笔记二(信号槽)

简介: Qt6学习笔记二(信号槽)

一、信号槽

信号:signal (比如click)

槽: slot

实现wedget窗口的关闭

(例子实现接着Qt学习笔记一的过程)

点击myBtn实现wedget窗口关闭

参数1:信号的发送者

参数2:发送的信号(函数地址)

参数3: 信号的接收者

参数4: 处理的槽函数

//需求:点击我的按钮 关闭窗口
    //参数1:信号的发送者   参数2:发送的信号(函数地址)  参数3: 信号的接收者   参数4: 处理的槽函数
    connect(myBtn,&QPushButton::clicked,this,&QWidget::close);
//    connect(myBtn,&MyPushButton::clicked,this,&Widget::close);//因为继承关系,也可以直接通过这种调用信号和槽函数

过程:

要找按钮的信号,可以使用帮助文档搜索QPushButton然后找到signal

需要找到wedget的槽,可以帮助文档搜QWedget然后找到slot

自动补全时,那种函数名前带有波纹图样的就是信号

总结

二、自定义信号和槽

(新建一个工程,过程中选择cmake,初始为widget) 创建工程结束后如下图所示

首先创建Teacher类,由于它不属于任何控件,因此选择QObject作为基类,这样如果setParent,就可以实现自动释放

案例:

Teacher类 老师类

Student类 学生类

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

创建Teacher类

teacher.h

signal下,添加一个hungry(饥饿)信号

#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);
signals:
    //自定义信号  写到signals下
    //返回值是void,只需要声明,不需要实现
    //可以有参数,可以重载
    void hungry();
};
#endif // TEACHER_H

teacher.cpp

(无修改)

#include "teacher.h"
Teacher::Teacher(QObject *parent)
    : QObject{parent}
{
}

创建Student类

student.h

pulic slots下面定义一个槽函数treat(请客)

#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);
signals:
public slots:
    //早期Qt版本 必须要写到public slots,高级版本可以写到public 或者全局下
    //返回值void ,需要声明,也需要实现
    //可以有参数,可以发生重载
    void treat();
};
#endif // STUDENT_H

student.cpp

student槽函数的实现

#include "student.h"
#include<QDebug>
Student::Student(QObject *parent)
    : QObject{parent}
{
}
void Student::treat()
{
    qDebug()<<"Invite the teacher to dinner";
}

信号连接槽函数与触发信号

在widget.h中定义了 Student对象,Teacher对象,以及 下课的函数

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include"teacher.h"
#include"student.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    Ui::Widget *ui;
    Teacher* zt;
    Student* st;
    void classIsOver();
};
#endif // WIDGET_H

widget.cpp

创建老师、学生对象 ,连接信号(饥饿)与槽函数(请客)

调用下课 函数,触发老师饥饿信号

#include "widget.h"
#include "./ui_widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //创建一个老师对象
    this->zt=new Teacher(this);
    //创建一个学生对象
    this->st=new Student(this);
    //老师饿了  学生请客的连接
    connect(zt,&Teacher::hungry,st,&Student::treat);
    //调用下课函数
    classIsOver();
}
Widget::~Widget()
{
    delete ui;
}
void Widget::classIsOver()
{
    //下课函数,调用  出发老师饿了信号
    emit zt->hungry();//emit表示发射信号的意思
}

总结

三、自定义的信号和槽发生重载

重载信号和槽函数

比如Teacher类中对信号发生 重载

一个是无参,一个是有参

void hungry();
void hungry(QString foodName);

Student类对槽函数发生重载

void treat();
void treat(QString foodName);

对重载的信号和槽进行连接

由于直接用函数名会产生二义性,因此要定义函数指针,指定是有参的那个

然后讲 信号和槽函数 的函数指针 传入即可

//连接带参数的 信号和槽
    void(Teacher::*teacherSignal)(QString) = &Teacher::hungry;//定义一个函数指针,指向有参的
    void(Student::*studentSlot)(QString) = &Student::treat;
//    connect(zt,&Teacher::hungry,st,&Student::treat);如果直接传这个会产生二义性,因为重载了一个有参的。如果没有重载,可以这么用
    connect(zt,teacherSignal,st,studentSlot);

补充

另外在void Student::treat(QString foodName)实现过程中,发现chicken带了引号

如果不想用引号,可以 .toUtf8().data()

void Student::treat(QString foodName)
{
    //QString 转成 char* 先转成QByteArray(.toUtf8())  再转char* (.data())
    qDebug()<<"Invite the teacher to eat "<<foodName.toUtf8().data();
}

总结

四、信号连接信号

点击按钮->触发下课->触发老师饿了->学生请客

点击按钮触发下课,触发老师饿,触发学生请客

//点击一个 下课按钮,再触发下课
    QPushButton *btn = new QPushButton("classOver",this);
    //重置窗口大小
    this->resize(600,400);
    //点击按钮  触发下课
    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);
    //断开信号(参数是和connect一样的)
    disconnect(zt,teacherSignal2,st,studentSlot2);

总结

五、信号槽连接的一些注意点和Qt4版本信号槽连接

1.信号是可以连接信号

2.一个信号 可以连接 多个槽函数

3.多个信号 可以连接 同一个槽函数

4.信号和槽函数的参数 必须类型一一对应

5.信号和槽的参数个数是不是要一致? 信号参数的个数 可以多余槽参数个数。 反之不行

另外Qt4的信号槽连接就不介绍了,它的优点:参数直观。 缺点:类型不做检测

六、信号槽连接中使用lambda表达式

//lambda表达式作为信号槽连接的槽函数 (mutable关键字,用于修饰值传递变量,使得值传递拷贝的结果可以修改)
    QPushButton* btn2=new QPushButton("second btn",this);
    btn2->move(100,100);
    int m=100;
    connect(btn2,&QPushButton::clicked,this,[m]()mutable{m=m+10;qDebug()<<m;});
    //lambda表达式,如果返回int, 返回值用->int。直接加括号可以调用
    int ret=[m]()->int{return m;}();
    qDebug()<<"ret = "<<ret;
    //利用lambda表示,实现点击按钮,关闭窗口
    QPushButton *btn3=new QPushButton("close widget",this);
    btn3->move(300,100);
    connect(btn3,&QPushButton::clicked,this,[this](){
        emit zt->hungry("chicken");
        this->close();
    });
    //如果第3个参数是this,使用lambda表达式,可以省略第三个参数,直接输入lambda表达式就行
    connect(btn3,&QPushButton::clicked,[this](){
        emit zt->hungry("chicken");
        this->close();
    });

七、总结

八、练习

设置一个按钮,点击open,可以显示一个窗口,并按钮文本变成close。

点击close,关闭刚才打开的窗口,并按钮文本变成open

和之前一样的方式创建工程

widget.cpp

#include "widget.h"
#include "./ui_widget.h"
#include<QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton *btn1=new QPushButton("open",this);
    this->resize(600,600);
    QWidget *subW=new QWidget;
    connect(btn1,&QPushButton::clicked,this,[=,flag=true]()mutable{
       if(flag==true){
           btn1->setText("close");
           flag=false;
           subW->show();
       }
       else if(flag==false){
           btn1->setText("open");
           flag=true;
           subW->close();
       }
    });
}
Widget::~Widget()
{
    delete ui;
}

九、其他

QT智能提示可能有些不舒服,提示出来慢

于是设置一下

工具-》选项-》文本编辑器-》Completion

中的Timeout in ms(提示延迟):可以设置小一点(看个人习惯)

Character threshold(字符阈值):输入超过阈值个字符就可以代码提示


相关文章
|
22天前
【Qt 学习笔记】按钮实现helloworld | 信号与槽概述
【Qt 学习笔记】按钮实现helloworld | 信号与槽概述
23 0
|
4月前
|
C++
Qt6学习笔记九(自定义控件封装)
Qt6学习笔记九(自定义控件封装)
66 0
|
22天前
|
安全 编译器 开发者
【Qt 学习笔记】Qt信号和槽的其他说明及Lambda表达式
【Qt 学习笔记】Qt信号和槽的其他说明及Lambda表达式
34 0
|
4月前
Qt6学习笔记三(QMainWindow、菜单栏、工具栏、状态栏、铆接部件、核心部件)
Qt6学习笔记三(QMainWindow、菜单栏、工具栏、状态栏、铆接部件、核心部件)
42 0
|
2月前
|
消息中间件 存储 安全
深入理解 Qt 信号槽:高效沟通的桥梁
深入理解 Qt 信号槽:高效沟通的桥梁
54 1
|
4月前
|
容器
Qt6学习笔记七(ToolButton、RadioButton、GroupBox、CheckBox、ListWidget、TreeWidget、TableWidget)
Qt6学习笔记七(ToolButton、RadioButton、GroupBox、CheckBox、ListWidget、TreeWidget、TableWidget)
45 0
|
22天前
|
开发框架 数据可视化 前端开发
【Qt 学习笔记】Qt控件概述
【Qt 学习笔记】Qt控件概述
21 0
|
22天前
|
编译器 C++ 索引
【Qt 学习笔记】详解Qt中的信号和槽
【Qt 学习笔记】详解Qt中的信号和槽
31 0
|
22天前
【Qt 学习笔记】输入框实现helloworld | QLineEdit的使用
【Qt 学习笔记】输入框实现helloworld | QLineEdit的使用
20 1
|
22天前
|
XML 自然语言处理 C++
【Qt 学习笔记】使用两种方式实现helloworld
【Qt 学习笔记】使用两种方式实现helloworld
23 1

推荐镜像

更多