当前位置: 首页 > web >正文

Qt坐标系 + 信号和槽 + connect函数(8)

文章目录

  • Qt坐标系
  • 信号和槽
  • connect函数
    • connect函数的介绍
    • connect函数具体的使用方式
      • 一个简单的例子
  • 两个问题
    • 咋知道的QPushButton有一个clicked信号
    • 官方文档找不到相关线索怎么办

简介:上篇文章:Qt 通过控件按钮实现hello world + 命名规范(7)。通过按钮方式创建hello world程序中涉及到connect函数以及信号和槽部分知识,这篇文章主要是对这部分的知识做一个相关补充,再介绍Qt坐标系的相关知识。欢迎各位看官好友浏览,下篇文章见!

Qt坐标系

平面直角坐标系(笛卡尔坐标系)分为两种坐标系,一种是数学上的坐标系(右手坐标系),一种是计算机中的坐标系(左手坐标系)

在这里插入图片描述

坐标系的原点(0,0)就是屏幕的左上角或窗口的左上角。给Qt的某个控件设置位置的时候就需要指定坐标,对于这个控件来说,坐标系原点就是相对于父窗口控件的(0,0)。比如下方QPushButton的父元素/父控件/父窗口就是QWidget,而QWidget没有父元素(NULL),就相当于父元素就是整个显示器桌面(电脑屏幕)

在这里插入图片描述

下面红色所框的范围就是代码中创建的Widget的范围,此时默认情况下按钮就是在(0,0)位置处(左上角)。可以使用move函数来设置该按钮的位置

在这里插入图片描述

#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* myButton = new QPushButton(this);myButton->setText("按钮");myButton->move(400,500);this->move(100,200);
}Widget::~Widget()
{delete ui;
}

在这里插入图片描述

move(400,500)坐标背后的单位是像素。显示器它本质上就是由一大堆可以发光的小亮点或小灯泡构成的,如果你使用手机对着屏幕去拍照,把对焦放到最大,是有可能看到像素的。而且在电脑的设置中我们能看到:显示器分辨率 1920 X 1080。这表示的是,水平方向上有1920个像素(亮点),垂直方向上有1080个像素,那显示器亮点数量越多,它的画面就越好,那显示器的价格也随之越贵。分辨率1920 X 1080 :1080p分辨率2560 X 1440 :2k分辨率3840 X 2160 :4k其中2k与4k分为数字电影与消费级,上述介绍的是消费级中的2k与4k。下面的图片是我用手机拍电脑屏幕聚焦放到最大的结果

在这里插入图片描述

信号和槽

在Linux中,信号Sigal是系统内部的通知机制,也是进程间通信的方式。而Qt中的信号和Linux中的信号虽然不是一样的概念,但是确实有相似之处在Qt中谈到信号时,肯定涉及到下面的三个要素

  • 信号源:由哪个控件发出的信号
  • 信号的类型:用户进行不同的操作,就可能触发不同的信号。比如点击按钮的时候就会触发点击信号,在输入框中移动光标,就会触发移动光标的信号
  • 信号的处理方式:注册信号处理函数(槽(slot)函数),在信号被触发的时候自动调用执行。在Qt中可以使用connect这样的函数,把一个信号和槽关联起来,后续只要信号触发了,Qt就会自动的执行槽函数,而所谓的槽函数本质上也是一种回调函数

关于这个回调函数,在C语言进阶中的指针进阶用到了函数指针去实现转移表,降低代码的圈复杂度,qsort实现回调函数效果。在C++STL中用到的仿函数和lambda表达式。在Linux中有信号处理函数,线程的入口函数和epoll基于回调的机制

举个形象的例子来帮助理解:

  • 信号源:你女朋友
  • 信号的类型:今天面色不善
  • 信号的处理方式:在脑子里面快速搜索各种可能,最终确定出最可能的一个原因是:每个月总有那么几天身体不舒服。OK自动帮忙去煮一杯红糖水

在上述操作过程中,都是提前把不同的信号的处理方式都准备好了,再去触发信号。比如,如何煮一杯红糖水,这个我方法我已经会了,将这个方法与面色不善这个信号给关联起来,一触发信号就能开煮,而不是在网上搜索如何煮红糖水。要特别注意,在Qt中一定是先关联信号和槽,然后再触发这个信号,这里的顺序不能颠倒,如果先触发这个信号,都没有关联起来,那咋知道如何去处理这个信号呢?

connect函数

connect函数的介绍

connect这个函数和Linux TCP socket中建立连接的函数并没有任何关系,只是名字恰巧一样罢了。connect函数是QObject提供的静态成员函数,又因为Qt中提供的这些控件类本身是存在一定的继承关系的,而QObject类是其它Qt内置类的祖宗所以connect使用没有任何限制,想到哪个类中使用就使用,下面是其中一部分类继承关系图。在Java中也存在类似的设定,Java所有的类都是继承自Object类

这里手误了,是QObject

connect函数具体的使用方式

这里的相关用法也可以去参考这篇内容中的通过按钮方式创建hello world程序:Qt 通过控件按钮实现hello world + 命名规范(7)。

// 在Assistant中输入connect
connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
  • const QObject *sender:描述了当前信号是哪个控件发出来的
  • const char *signal:信号的类型
  • const QObject *receiver:哪个控件对象负责处理信号
  • const char *method:这个对象要怎么处理(输入要处理信号的对象所提供的成员函数
  • Qt::ConnectionType type = Qt::AutoConnection:暂时先不考虑,也很少使用这个

一个简单的例子

界面上包含一个按钮,用户点击按钮,则关闭窗口

#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* myButton = new QPushButton(this);myButton->setText("按钮");myButton->move(200,200);connect(myButton, &QPushButton::clicked, this, &Widget::close);
}Widget::~Widget()
{delete ui;
}
  • (myButton, &QPushButton::clicked)connect要求这两参数必须是匹配的,myButton的类型如果是QPushButton*,那第二个参数的信号必须是QPushButton内置的信号(或者是它父类的信号),不能是一个其他的类,比如QLineEdit的信号。所谓的信号也就是Qt中对象内部提供的一些成员函数
  • (this, &Widget::close)这里close是QWidget内置的槽函数,Widget继承自QWidget,也就继承了父类的槽函数,而close槽函数功能已经是人家内部实现好了,无需我们去关心,具体的作用就是关闭当前的窗口/控件
  • 解析click与clicked;从单词的层次看,一个是一般现在形式,一个是过去分词形式。(这个参数是信号类型)那clicked它的意思就是:鼠标点完了后,这就是要触发的点击信号。而click它是一个槽函数,它的作用就是在调用的时候相当于点击了一下按钮

在这里插入图片描述

两个问题

咋知道的QPushButton有一个clicked信号

如果想知道Qt里到底提供了哪些内置的信号和槽可以让我们直接使用呢?那唯一的方式就是:多看文档其次在翻阅文档的时候,如果在当前类中没有找到对应的线索,可以看看这个类的父类

在这里插入图片描述

QPushButton它的父类是QAbstractButton,单词abstract的意思是抽象的,摘要。Qt中会提供好几种按钮,然后将这些按钮存在的一些共性内容给提取出来,放到QAbstractButton类里面

在这里插入图片描述

当我们要去查clicked信号时,会发现QPushButton并没有这个信号函数,那就去它的父类找,当查阅到文档中的信号时,最重点就是关注信号的发送时机(也就是用户进行了啥样的操作,就能产生这个信号

官方文档找不到相关线索怎么办

&QPushButton::clicked&widget::close这两是一个函数指针,那在connect函数具体的使用方式中提到,它的形参不是要求传入的是一个 const char* ,这char* 和 函数指针能是同一个东西吗?虽然同为指针,不过很明显这两压根不是同一个东西,char* 的类型就叫做char*void clicked(bool checked = fasle);该函数的函数指针类型是void(*)();而且它虽与bool(*)();同为函数指针,但它们的类型也是不一致的,那在C++中是不允许你使用两个不同的指针类型相互赋值的(因为函数传参本质上就是赋值)。那在文档中也找不出线索了,好像没辙了,这时就要进入到库中看看这个connect函数到底是怎么写的

鼠标放在该类名或函数上,按住ctrl键+鼠标左键进去,按住alt + 左方向键可以返回

在这里插入图片描述

文档中的这个函数声明是以前旧版本的Qt的connect函数的声明。以前板本中,传参的写法和现在其实也是有区别的。之前给信号参数传参,要搭配一个SIGNAL宏,给槽参数传参,要搭配一个SLOT宏才能将传入的函数指针转成 char*。connect(mybutton, SIGNAL(&QPushButton::clicked), this, SLOT(&Widget::close))

在这里插入图片描述

可能因为一些原因,官方文档没有及时更新,那我们就去库中看看。从Qt 5开始,对上述写法做出了简化,就不再需要写SIGNAL 和SLOT 宏了,直接给connect 提供了重载版本。在重载版本中,第二个参数和第四个参数成了泛型参数,允许咱们传入任意类型的函数指针了。(C++泛型编程其次使用Qt封装的类型萃取器,此时 connect 函数就带有了一定的 参数检查功能,如果你传入的第一个参数和第二个参数不匹配,或者第三个参数和第四个参数不匹配(不匹配,2,4参数的函数指针,不是1,3参数的成员函数)此时代码编译出错

http://www.xdnf.cn/news/5392.html

相关文章:

  • 从InfluxDB到StarRocks:Grab实现Spark监控平台10倍性能提升
  • 技术书籍推荐(002)
  • MySQL数据库下篇
  • 缓存(4):常见缓存 概念、问题、现象 及 预防问题
  • [项目总结] 抽奖系统项目技术应用总结
  • 小土堆pytorch--torchvision中的数据集的使用dataloader的使用
  • 设计模式之工厂模式(二):实际案例
  • 支持selenium的chrome driver更新到136.0.7103.92
  • 飞蛾扑火算法matlab实现
  • 【仿真】【具身智能仿真】Isaac Simlab云端部署(入门学习性价比最高的方式)
  • 深入解析多选字段的存储与查询:从位运算到数据库设计的最佳实践
  • 仿真生成激光干涉包裹相位数据-用于深度学习训练!
  • Java SE(11)——内部类
  • JavaSE核心知识点02面向对象编程02-07(枚举)
  • 【Bootstrap V4系列】学习入门教程之 组件-巨幕(Jumbotron)和列表组(List group)
  • 常用的rerank模型有哪些?都有什么优势?
  • Python 自动化脚本开发秘籍:从入门到实战进阶(6/10)
  • 螺旋驱动管道机器人的结构设计
  • OpenWrt开发第7篇:OpenWrt配置支持Web界面
  • 网址为 http://xxx:xxxx/的网页可能暂时无法连接,或者它已永久性地移动到了新网址
  • Linux共享内存深度解析:从内核机制到云原生应用
  • DAY 17 训练
  • 基于Dockers的Bitwarden的私有本地部署
  • 动态规划之二维费用的背包问题解析
  • CDGP历次主观题真题回忆
  • 深入浅出之STL源码分析4_类模版
  • Bitacora:基因组组件中基因家族识别和注释的综合工具
  • PTA:jmu-ds-拓扑排序
  • 安装:Kali2025+Docker
  • 【Redis】string 字符串