> 作者:დ旧言~
> 座右铭:松树千年终是朽,槿花一日自为荣。
> 目标:了解QT中的窗口坐标,并能熟练使用信号和槽。
> 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安!
> 专栏选自:QT从基础到入门_დ旧言~的博客-CSDN博客
> 望小伙伴们点赞👍收藏✨加关注哟💕💕
一、Qt 中的窗口坐标
在Qt中坐标系的开始(原点)是左上角(0,0),从在左上角往右依次增加的是x轴,从左上角往下依次增加的是y轴:
- 给 QT 的某个控件(如:嵌套窗口),设置位置就需要指定坐标,对于这个控件来说,坐标系原点就是相对于父窗口 / 控件的
- QPushButton 的父元素/父控件/父窗口 就是 QWidget
- QWidget 没有父元素(NULL),就相当于父元素就是整个显示器桌面了

二、信号与槽的认识
2.1、背景
- 看到这里,其实也让我们想起 Linux 的信号 Signal
- 系统内部的通知机制
- 进程间通信的方式
这里我们还要补充一些概念,如下:
- 信号源:谁发的信号。
- 信号的类型:哪种类别的信号。
- 信号的处理方式:注册信号处理函数,在信号被触发的时候自动调用执行。
2.2、基本概念
Qt 中谈到信号,也涉及到三个因素:
- 信号源:由哪个控件发出的信号
- 信号的类型:用户进行不同的操作就可能触发不同的信号,不同的操作如下:
- 点击按钮触发点击信号
- 在输入框内移动光标,触发移动光标的信号
- 勾选一个复选框
- 选择一个下拉框,都会触发不同的信号
- 我们这里写的 Gui 程序就是要让用户进行操作,就是要和用户进行交互
在 Qt 中,用户和控件的每次交互过程称为一个事件。比如 "用户点击按钮" 是一个事件,"用户关闭窗口" 也是一个事件:
- 每个事件都会发出一个信号,例如用户点击按钮会发出**"按钮被点击"的信号,用户关闭窗口会发出"窗口被关闭"**的信号。
- Qt 中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。
- 例如,按钮所在的窗口接收到"按钮被点击"的信号后,会做出"关闭自己"的响应动作;再比如输入框自己接收到"输入框被点击"的信号后,会做出"显示闪烁的光标,等待用户输入数据"的响应动作
- 在 Qt中,对信号做出的响应动作就称之为槽。
- 信号的处理方式:槽(slot) => 函数
比如,"按钮"和"窗口"本身是两个独立的控件,点击 "按钮" 并不会对 "窗口" 造成任何影响。通过信号和槽机制,可以将"按钮"和"窗口"关联起来,实现 "点击按钮会使窗口关闭" 的效果:
2.2.1、信号的本质
信号 是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时0t对应的窗口类会发出某个信号,以此对用户的操作做出反应。因此,信号的本质就是事件。如:
- 按钮单击、双击
- 窗口刷新
- 鼠标移动、鼠标按下、鼠标释放
- 键盘输入
那么在 Qt 中信号是通过什么形式呈现给使用者的呢:
- 我们对哪个窗口进行操作,哪个窗口就可以捕捉到这些被触发的事件。
- 对于使用者来说触发了一个事件我们就可以得到 Ot框架给我们发出的某个特定信号。
- 信号的呈现形式就是函数,也就是说某个事件产生了,Qt框架就会调用某个对应的信号函数,通知使用者。
2.2.2、槽的本质
槽(Slot)就是对信号响应的函数:
槽就是一个函数,与一般的 C++ 函数是一样的,可以定义在类的任何位置(public、protected 或 private),可以具有任何参数,可以被重载,也可以被直接调用(但是不能有默认参数)。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行
(1)信号和槽机制底层是通过函数间的相互调用实现的。每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数:
- 例如:"按钮被按下"这个信号可以用 clicked() 函数表示,"窗口关闭"这个槽可以用 close()函数表示,
- 假如使用信号和槽机制实现:"点击按钮会关闭窗口"的功能,其实就是 clicked()函数 调用 close() 函数 的效果。
(2)信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:
- 信号函数用 signals 关键字修饰,槽函数用 public slots、protected slots 或者 private slots 修饰。
- signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数;信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。
三、信号与槽的使用
3.1、连接信号与槽
在Qt中,
QObject类
提供了⼀个静态成员函数connect()
,该函数专门用来关联指定的信号函数和槽函数。
关于 QObject 类:
- QObject是Qt内置的父类,Qt中提供的很多类都是直接或者间接继承自 QObject.
- 这一点在 Java 中也有类似的设定,Java 中所有的类都是继承自 Object 类
connect() 函数原型:
cpp
connect (const QObject *sender,
const char * signal,
const QObject * receiver,
const char * method,
Qt::ConnectionType type = Qt::AutoConnection )
参数声明:
- sender:信号的发送者,描述了当前信号由 哪个控件 发出来
- signal:发送的信号(信号函数),信号的类型
- receiver:信号的接收者,哪个对象(控件)负责处理
- method:接收信号的槽函数,这个对象该怎么处理(要处理对象提供的槽函数)
- type:用于指定关联方式,默认的关联方式为 Qt::AutoConnection,通常不需要手动设定。
3.2、查看内置信号和槽
如下述示例,要查询 "按钮" 的信号,在帮助文档中输入:QPushButton

- 首先可以在"Contents"中寻找关键字signals
- 如果没有找到,继续去父类中查找。因此我们去他的父类
QAbstractButton
中继续查找关键字signals
四、定义信号和槽
4.1、基本语法
① 自定义信号函数书写规范:
- 自定义信号函数必须写到
"signals"
下; - 返回值为void,只需要声明,不需要实现;
- 可以有参数,也可以发生重载;
② 自定义槽函数书写规范:
- 早期的Qt版本要求槽函数必须写到
"publicslots"
下,但是现在高级版本的Qt允许写到类的 "public"作用域中或者全局下; - 返回值为void,需要声明,也需要实现;
- 可以有参数,可以发生重载;
③ 发送信号 使用"emit"关键字发送信号:
- "emit"是⼀个空的宏。"emit"其实是可选的,没有什么含义,只 是为了提醒开发人员。
4.2、信号和槽存在的意义
所谓的信号槽,其实要解决的问题--> 就是响应用户的操作:
- 信号槽,其实就是 GUI 开发的各种框架中,比较有特色的存在
而其他的 GUI 开发框架相比于 信号槽,方式都更要简洁一些:
- 比如网页开发(js + dom api)
- 网页开发中响应用户操作,主要就是挂回调函数
优点: 松散耦合
信号发送者不需要知道发出的信号被哪个对象的槽函数接收,槽函数也不需要知道哪些信号关联了自Qt的信号槽机制保证了信号与槽函数的调用。支持信号槽机制的类或者父类必须继承于 QObject类。
缺点: 效率较低
与回调函数相比,信号和槽稍微慢一些,因为它们提供了更高的灵活性,尽管在实际应用程序中差别不大。通过信号调用的槽函数比直接调用的速度慢约10倍(这是定位信号的接收对象所需的开销;遍历所有关联;编组/解组传递的参数;多线程时,信号可能需要排队),这种调用速度对性能要求不是非常高的场景是可以忽略的,是可以满足绝大部分场景。
五、结束语
今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。
