对象树、QT的坐标系、信号和槽机制

news2024/11/26 16:53:42

目录

1、QT中什么是对象树

2、QT的坐标系

3、信号和槽机制

3.1、信号槽的理解

3.2、信号槽的工作原理

3.3、信号槽的使用

3.3.1、系统的信号和槽

3.3.2、自定义信号和槽函数

3.3.3、信号和槽函数之间的参数传递

3.3.4、信号和槽的注意


1、QT中什么是对象树

在创建 QObject 对象时,可以提供一个其父对象,我们创建 的这个 QObject 对象会自动
添加到其父对象的 children()列表。
当父对象析构的时候,这个列表中的所有对象也会 被析构。(注意,这 里的父对象并不是继承意义上的父类!)
QWidget 继承自 QObject,因此也继承了这种对象树关系。一个孩子自 动地成为父组件
的一个子组件
我们也可以自己删除子对象,它们会自动从其父对象列表中删除
综上所述:所有的控件 尽量在 堆区 创建

2、QT的坐标系

以左上角为原点(0,0),X 向右增加,Y 向下增加

3、信号和槽机制

3.1、信号槽的理解

具体的信号是不需要实现具体要执行的动作,这个只需要定义函数,不需要实现函数体,信号接受者的槽函数要定义函数,还要实现函数体,来实现信号发起者的命令

3.2、信号槽的工作原理

某个事件发生之后 ,比如,按钮检测到自己被点击了一下, 它就会发出一个信号(signal) 。这种发出是没有目的的,类似广播( 谁都能听到或者看到,比如项羽摔杯的发出的响声和动作 )。 如果有对象对这个信号感兴趣,它就会使用连接(connect)函数 ,意思是, 将想要处理的信号和自己的一个函数(称为槽(lot))绑定来处理这个信号 。也就是说, 当信号发出时,被连接 的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。

3.3、信号槽的使用

信号槽有系统自定义的,但是系统自定义的只能解决 80 % 的问题,剩下的 20 % 需要我们自己定义

3.3.1、系统的信号和槽

3.3.1.1、查找系统的信号(找不到就自定义)

  

3.3.1.2、查找系统的槽(找不到就自定义)

由于当前的 窗口 是 Widget,所以 btn 被按下发出信号,Widget 响应,做出关闭动作,所以去 Widget 中查找 关闭窗口函数

 
3.3.1.3、使用按钮关闭当前主窗口

#include "widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //设置主窗口大小
    this->resize(400,300);
    //创建一个按钮
    QPushButton *btn = new QPushButton("关闭", this);
#if 0    //通过 0 和 1来控制使用 QT5 还是 QT4
    // 建立信号和槽的关系(Qt5的方式),向下兼容,QT5兼容QT4,拿到&QPushButton::clicked的入口地址
    // 拿到&Widget::close的入口地址
    connect( btn, &QPushButton::clicked  ,this, &Widget::close );
#else
    // 建立信号和槽的关系(Qt4的方式) SIGNAL将()里面当成字符串看待 不会判断信号是否存在
    // 所以 QT4 是最稳妥的方式,QT5 能兼容
    connect( btn, SIGNAL(clicked())  ,this, SLOT(close()) );
#endif
}

Widget::~Widget()
{

}

3.3.2、自定义信号和槽函数

可以自定义信号选择系统槽函数,可以选择系统信号自定义槽函数,或者同时自定义信号和槽函数,根据需求选择一方即可

点击添加文件,添加发出信号者的类和接受信号者的类,并且使他们符合 QT 的槽机制(创建文件时选择 Widget 作为他们的基类),如下

#include "teacher.h"

Teacher::Teacher(QWidget *parent) : QWidget(parent)
{
//信号发出者
}
#include "student.h"

Student::Student(QWidget *parent) : QWidget(parent)
{
//信号接受者
}
创建文件时如果不选择 Widget 作为他们的基类,那么创建的类就是普普通通的类,是不会拥有 QT 的信号槽机制
定义信号: 
在 teacher.h中类的关键字signals下实现:
#ifndef TEACHER_H
#define TEACHER_H

#include <QWidget>
class Teacher : public QWidget
{
    Q_OBJECT
public:
    explicit Teacher(QWidget *parent = 0);

signals:
    //信号的返回值类型为void 可以有参(重载),不能实现函数体
    void hungury(void);

public slots:
};

#endif // TEACHER_H
定义槽函数:
在 student.h中 类的关键字public slots下实现:

#ifndef STUDENT_H
#define STUDENT_H

#include <QWidget>
#include <QDebug>
class Student : public QWidget
{
    Q_OBJECT
public:
    explicit Student(QWidget *parent = 0);

signals:

public slots:
    //槽函数返回值类型为void ,可以有参数(重载),槽函数的参数就是接受的信号的参数,信号有参数槽函数就必须有参数, 必须实现函数体,接到信号之后要执行的具体动作
    void treat(void)
    {
        qDebug()<<"请老师吃饭了"<<endl;     //相当于打印输出,QT中没有 cout
    }
};

#endif // STUDENT_H

建立老师和学生的关系

在 widget.cpp中建立老师和学生的关系_即老师饿了的信号,学生就执行请吃饭的动作

#include "widget.h"
#include "teacher.h"
#include "student.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->resize(400,300);
    //实例化老师的控件
    Teacher *tea = new Teacher(this);
    //实例化学生的控件
    Student *stu = new Student(this);

    //建立老师和学生的关系,connect(tea,"饿了",stu,"请吃饭")
    connect(tea,&Teacher::hungury,stu,&Student::treat);


}

Widget::~Widget()
{

}
但是现在问题是——》老师什么时候饿了,也即缺少信号的发起过程,所以设置按钮,点击按钮时,老师下课了,说饿了,学生请吃饭,所以要在 teacher.h中建立 Teacher 类的槽函数

在 widget.cpp中实现 按钮和 老师的关系建立

 

最后在   teacher.h中 实现当老师下课的时候,发出老师饿了的信号

上述流程执行如下

 widget.cpp中的源代码如下

#include "widget.h"
#include "teacher.h"
#include "student.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->resize(400,300);
    //实例化老师的控件
    Teacher *tea = new Teacher(this);
    //实例化学生的控件
    Student *stu = new Student(this);

# if 1
    //建立老师和学生的关系,connect(tea,"饿了",stu,"请吃饭")
    connect(tea,&Teacher::hungury,stu,&Student::treat);
# else
# endif
    //但是现在问题是——》老师什么时候饿了,也即缺少信号的发起过程,所以设置按钮,点击按钮时,老师下课了,说饿了,学生请吃饭
    QPushButton *btn = new QPushButton("下课", this);

    //建立按钮和老师之间的关系,这个时候 btn 就是一个信号,老师是一个槽函数,按动按钮,老师下课了
    connect(btn, &QPushButton::clicked, tea, &Teacher::classOver);
}

Widget::~Widget()
{

}

3.3.3、信号和槽函数之间的参数传递

widget.cpp中实现如下

#include "widget.h"
#include "teacher.h"
#include "student.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->resize(400,300);
    //实例化老师的控件
    Teacher *tea = new Teacher(this);
    //实例化学生的控件
    Student *stu = new Student(this);

# if 1
    //无参使用这种(QT5的方式)
    //建立老师和学生的关系,connect(tea,"饿了",stu,"请吃饭")
    void (Teacher:: *p1)() = &Teacher::hungury;
    void (Student:: *p2)() = &Student::treat;
    connect(tea,p1,stu,p2);
# else
    //有参使用这种,当 信号 或者 槽 发生 重载使,使用函数指针作为区分
    void (Teacher:: *p1)(QString) = &Teacher::hungury;
    void (Student:: *p2)(QString) = &Student::treat;
    connect(tea,p1,stu,p2);
# endif
    //但是现在问题是——》老师什么时候饿了,也即缺少信号的发起过程,所以设置按钮,点击按钮时,老师下课了,说饿了,学生请吃饭
    QPushButton *btn = new QPushButton("下课", this);

    //建立按钮和老师之间的关系,这个时候 btn 就是一个信号,老师是一个槽函数,按动按钮,老师下课了
    connect(btn, &QPushButton::clicked, tea, &Teacher::classOver);
}

Widget::~Widget()
{

}

teacher.h中的 Teacher 类中,hungury信号有参数,触发信号的classOver槽函数中的hungury信号必然有参数

#ifndef TEACHER_H
#define TEACHER_H

#include <QWidget>
#include <QDebug>
class Teacher : public QWidget
{
    Q_OBJECT
public:
    explicit Teacher(QWidget *parent = 0);

signals:
    //信号的返回值类型为void 可以有参(重载),不能实现函数体
    void hungury(void);
    //参数重载
    void hungury(QString foodName);

public slots:
    //下课的槽函数
    void classOver(void)
    {
        qDebug()<<"下课了"<<endl;
        //emit 发出老师饿了的信号

        emit this->hungury();
        emit this->hungury("兰州牛肉面");    //QT自动实现参数传递解析

    }
};

#endif // TEACHER_H

student.h 中的Student 类中,进行槽函数重载,实现参数传递

#ifndef STUDENT_H
#define STUDENT_H

#include <QWidget>
#include <QDebug>
class Student : public QWidget
{
    Q_OBJECT
public:
    explicit Student(QWidget *parent = 0);

signals:

public slots:
    //槽函数返回值类型为void ,可以有参数(重载),槽函数的参数就是接受的信号的参数,信号有参数槽函数就有参数, 必须实现函数体,接到信号之后要执行的具体动作
    void treat(void)
    {
        qDebug()<<"请老师吃饭了"<<endl;
    }
    void treat(QString foodName){
        qDebug()<<"请老师吃饭了"<<":"<<foodName<<endl;
    }
};

#endif // STUDENT_H

测试如下(无参和有参)

 

3.3.4、信号和槽的注意

一个信号 连接 多个槽
多个信号 连接 一个槽
disconnect取消信号和槽的连接
槽函数的参数 一定要 小于等于 信号的参数个数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/429216.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

重构·改善既有代码的设计.04之重构手法(下)完结

1. 前言 本文是代码重构系列的最后一篇啦。前面三篇《重构改善既有代码的设计.01之入门基础》、《重构改善既有代码的设计.02之代码的“坏味道”》、《重构改善既有代码的设计.03之重构手法&#xff08;上&#xff09;》介绍了基础入门&#xff0c;代码异味&#xff0c;还有部…

如何在ubuntu上搭建minio

由于腾讯的对象存储服务器&#xff08;COS&#xff09;的半年免费试用期已过&#xff0c;所以寻思鼓捣一下minio&#xff0c;试着在自己的服务器上搭建一套开源的minio对象存储系统。 单机部署基本上有以下两种方式。 一、直接安装 最基础的一种单机安装&#xff0c;这里不做…

记录-js基础练习题

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 隔行换色(%): window.onload function() {var aLi document.getElementsByTagName(li);for(var i 0; i < aLi.length; i){if(i%2 1){aLi[i].style.background #bfa;}} } <ul><li>…

微搭低代码学习之基础操作

低代码开发平台&#xff0c;是一种方便产生应用程序的平台软件&#xff0c;软件会开发环境让用户以图形化接口以及配置编写程序&#xff0c;而不是用传统的程序设计作法。此平台可能是针对 某些种类的应用而设计开发的&#xff0c;例如数据库、业务过程、以及用户界面。这类平台…

STM32锁芯片,解锁方法(J-LINK)

在烧写STM32时&#xff0c;不小心把usb口给弄掉了&#xff0c;然后就尴尬了&#xff0c;芯片被锁了。 烧写的时候报错&#xff0c;如下&#xff1a; 然后就搜了一下&#xff0c;大致有两个方法&#xff0c; 第一种需要通过接3.3V到板子上BOOT0重新上电第二种是直接通过软件…

Golang语言Windows环境搭建(Visual Studio Code)

一、Golang语言简介 二、Windows环境搭建 1、软件下载 Golang语言安装包官网下载地址&#xff1a;https://golang.google.cn/dl/ Visual Studio Code编辑器下载&#xff1a;https://code.visualstudio.com/ 2、Golang安装及环境变量配置 2.1 Golang语言安装包 双击安装…

可配置物料-文章资料分享

可配置物料项目一般很少用到&#xff0c;用到就是要命&#xff0c;推荐一下之前查资料收集的资料&#xff0c;分享给大家。感谢这位大佬收集的文章&#xff01; Variant Configuration (LO-VC) - Product Lifecycle Management - Support Wikihttps://archive.sap.com/document…

5V的LDO电源的WCCA分析-可靠性分析计算过程

WCCA(WorstCase Circuit Analysis)分析方法是一种电路可靠性分析设计技术&#xff0c;用来评估电路中各个器件同时发生变化时的性能&#xff0c;用于保证设计电路在整个生命周期的都可以可靠工作。通过WCCA分析&#xff0c;验证在上述参数在其容差范围内发生变化时&#xff0c;…

C++模板基础(八)

数值模板参数与模板模板参数 ● 模板可以接收&#xff08;编译期常量&#xff09;数值作为模板参数 – template class Str; template<int a> int fun(int x) {return x a; }int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);std::cout << fun…

相机SD卡无法读取提示格式化 相机SD卡无法读取怎么修复

相机SD卡中储存着的照片和视频&#xff0c;承载着我们美好的回忆。因为相机SD卡的容量有限&#xff0c;我们会定期对SD卡中的数据进行云盘备份&#xff0c;然后清理相机SD卡中的数据。在打开相机SD卡时&#xff0c;可能会遇到SD卡无法读取的情况。那么&#xff0c;相机SD卡无法…

Umi‘s Friends 冠名 VC MeetUP 酒会,圆满举办!

香港加密新政的整体目的是令虚拟资产交易明确化和合法化&#xff0c;通过不断完善的监管框架&#xff0c;促进香港虚拟资产行业的可持续和负责任地发展。在加强合规和持牌经营的监管思路下&#xff0c;长期审慎合规经营的老牌机构和项目&#xff0c;显然将获得先发优势。随着香…

开放式蓝牙耳机哪个好,分享几款舒适性高的开放式蓝牙耳机

开放式耳机的兴起是近几年来才出现的新概念&#xff0c;开放式耳机也是近几年来才开始流行起来&#xff0c;在我看来开放式耳机的兴起是科技进步的产物。随着蓝牙耳机技术和设备的发展&#xff0c;蓝牙耳机也越来越普及&#xff0c;但是也给用户带来了很多困扰。而开放式耳机就…

前端学习:HTML链接

目录 一、HTML超链接&#xff08;链接&#xff09; 二、HTML链接语法 三、target属性 target属性值展示 四、name属性 五、补充 关于创建电子邮件链接时如何发送邮件内容 在进行抄送时&#xff0c;需要使用关键字&#xff1a;cc 在进行密送时&#xff0c;需要使用关键字&a…

2.rabbitmq-linux安装

目录 一.环境准备 二.安装 一.环境准备 1.RabbitMQ版本 和 Erlang 版本兼容性关系 https://www.rabbitmq.com/which-erlang.html 2.官方安装包下载地址 【erlang下载地址】&#xff1a;https://github.com/rabbitmq/erlang-rpm/releases/tag/v21.3.1【rabbitmq下载地址】&a…

初识视觉SLAM(视觉SLAM十四讲ch1~ch2的收获与总结)

视觉SLAM14讲ch1和ch2的学习视觉SLAM14讲ch1和ch2的学习前言&#xff1a;一、SLAM是什么二、视觉SLAM14讲学习前的基础三、初步了解1. 小萝卜的例子2. 了解一些视觉SLAM的框架3. 一些数学问题的表述视觉SLAM14讲ch1和ch2的学习 前言&#xff1a; 开始学习视觉SLAM&#xff0c…

MMDetection 3.x 自定义数据集

最近在调研目标检测方面的技术实现&#xff0c;发现关于 MMDetection 自定义数据集的文章&#xff0c;多是就 2.x 版本进行描述的&#xff0c;而关于 3.x 版本的则比较少。有些文章在制作COCO数据集的时候&#xff0c;需要修改多处源代码&#xff0c;而这是没有必要的。本文主要…

【论文阅读】PureGaze

复现论文 PureGaze PureGaze Overview 这篇文章在purify的角度重新定义了gaze estimation的这个问题。 对提纯问题的定义 基于提纯的思想&#xff0c;可以把 gaze estimation 的问题定义为 g F( E( I ) )。 其中&#xff0c;E 是一个特征提取的函数&#xff0c;F 是一个回…

Java中的null总结

日常工作&#xff0c;遇见几次null的语法报错&#xff0c;整理以下Java中null&#xff1a; &#x1f341; null是一个关键字&#xff0c;对大小写敏感&#xff0c;像public、static… &#x1f341; null是所有引用数据类型的默认值&#xff08;int默认0、boolean默认false…)…

HTB-Jeeves

HTB-Jeeves信息收集80端口50000端口![在这里插入图片描述](https://img-blog.csdnimg.cn/5824bf345bc040ee9e449bebeade9495.png)开机kohsuke -> Administrator信息收集 80端口 ask jeeves是一款以回答用户问题提问的自然语言引擎&#xff0c;面对问题首先查看数据库里是否…

耳机输出电路中的耦合电容设计

分析耳机输出电路。 因为其中的输出耦合电容有6个这么多&#xff0c;有点奇怪。 耳机输出电路的实物外观长这样&#xff1a; 音频解码芯片&#xff08;型号WM8988&#xff09;输出音频信号&#xff0c;经过6个耦合电容&#xff0c;最终在耳机接口输出&#xff1a; 关键看靠近…