C++ Develop 4 --- 2020.8.19

记录开发


前言:

昨天学习到信号与槽,今天先把这部分内容补全;



5. 信号与槽(2)

查找 QtAssistant,发现 QPushButton 中的信号 signal 全是继承于父类;
在这里插入图片描述
点击 QAbstractButton 类,其 signal 有以下几种:
在这里插入图片描述
分别表示点击,按压,释放,切换,而现在我们按钮所要实现的功能是关闭窗口,故只需要信号 clicked 即可;
而信号的接收者应该是窗口,也即 QWidget 类,在助手中列出了一个 public slots,即公共槽函数:
在这里插入图片描述
点击第一个槽函数 close() 即为需要的函数:
在这里插入图片描述
“关闭当前窗口,若关闭成功返回 true,否则返回 false;”

那么代码语句如下:

connect(btn2, &QPushButton::clicked, this, &QWidget::close);

即可让 btn2 实现窗口关闭功能;

接下来自定义信号与槽:
创建两个类:
Teacher 类 老师类;
Student 类 学生类;
功能:
下课后,老师发送信号 饿了,学生响应信号 请客吃饭;

创建类时,由于是自定义,故直接继承最原始的父类 QObject,并且由于我选用的是 CMake 文件编译的,所以还要在 CMakeLists.txt 文件中加上如下语句:

if(ANDROID)
  add_library(SignalAndSlot SHARED
    main.cpp
    widget.cpp
    widget.h
    widget.ui
    teacher.h		//添加到工程;
    teacher.cpp		//添加到工程;
    student.cpp
    student.h
    ${TS_FILES}
  )
else()
  add_executable(SignalAndSlot
    main.cpp
    widget.cpp
    widget.h
    widget.ui
    teacher.h		//添加到工程;
    teacher.cpp		//添加到工程;
    student.cpp
    student.h
    ${TS_FILES}
  )

代码如下:

teacher.h

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);

signals:
    //自定义信号;
    //返回值是void,只需声明,不需要实现;
    //可以有参数,可以重载;
    void hungry();

};

#endif // TEACHER_H

student.h

#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

#include "student.h"
#include <QDebug>

Student::Student(QObject *parent) : QObject(parent)
{

}

void Student::treat()		//槽函数的实现;
{
    qDebug() << "treat the teacher";    //自动换行;
}

teacher.cpp 为空,除默认构造函数外没有需要实现的的函数;

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "teacher.h"    //注意1:若要在 widget 中创建对象,首先就要在头文件中将他们的头文件包含进来,然后在类中加入对象成员;
#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 *Li;    //添加到私有成员;
    Student *Zhang;

    void afterClass();

};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "./ui_widget.h"

//Teacher 类 老师类;
//Student 类 学生类;
//下课后,老师发送信号 饿了,学生响应信号 请客吃饭;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建一个老师对象;
    this -> Li = new Teacher(this);     //注意2:加父节点则不用考虑内存释放问题;

    //创建一个学生对象;
    this -> Zhang = new Student(this);

    //创建连接;
    connect(Li, &Teacher::hungry, Zhang, &Student::treat);      //注意3:触发连接要有个条件,例如:下课后;

    afterClass();   //注意4:先连接,再触发;
}

void Widget::afterClass()
{
    //除法饿了的信号;
    emit Li -> hungry();    //emit 触发信号;
}

Widget::~Widget()
{
    delete ui;
}


main.cpp

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

有以下几个注意事项:

注意1:若要在 widget 中创建对象,首先就要在头文件中将他们的头文件包含进来,然后在类中加入对象成员;
注意2:加父节点则不用考虑内存释放问题;
注意3:触发连接要有个条件,例如:下课后;
注意4:先连接,再触发;

运行结果:
在这里插入图片描述
成功打印 “treat the teacher”;

下面给个信号的带参重载版本;

添加代码:

void hungry(QString foodName);	//信号重载;
void treat(QString foodName);	//槽函数重载;
void Student::treat(QString foodName)	//槽函数实现;
{
    qDebug() << "treat the teacher with" << foodName;
}

但此时需要注意,当重载以后,connect 不能识别信号和槽函数地址到底是哪一个,这时候要用函数指针来指向一个函数地址,写法如下:
在这里插入图片描述

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

此时还需注意加上成员函数的成员域;

最后触发信号:

emit Li -> hungry("beef");

在这里插入图片描述
若要去除引号,则将 QString 转成 char*;
首先转成 QByteArray 再转 char*;

qDebug() << "treat the teacher with" << foodName.toUtf8().data();

用按钮来触发条件:

QPushButton *btn = new QPushButton("afertclass", this);

//点击按钮,触发下课;
connect(btn, &QPushButton::clicked, this, &Widget::afterClass);

断开连接:

disconnect(Li, teacherSignal, Zhang, studentSlot);

注:
1. 信号是可以连接信号的;
2. 一个信号可以连接多个槽函数;
3. 多个信号可以连接同一个槽函数;
4. 信号和槽函数的参数必须一一对应;
5. 信号的参数个数可以多于槽函数的参数个数,因为是从信号传递给槽,但相同的类型还是要对应;


透了;
一个下午才学了这么点…


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值