建个门户网站,博客转wordpress,wordpress多个菜单menu,培训方案网站建设目录
一、信号和槽概述
二、本质
底层实现
1. 函数间的相互调用
2. 类成员中的特殊角色
三、使用
四. 自定义信号和槽
1. 基本语法
(1) 自定义信号函数书写规范
(2) 自定义槽函数书写规范
(3) 发送信号
(4) 示例
A. 示例一
B. 示例二 —— 老师说“上课了”…目录
一、信号和槽概述
二、本质
底层实现
1. 函数间的相互调用
2. 类成员中的特殊角色
三、使用
四. 自定义信号和槽
1. 基本语法
(1) 自定义信号函数书写规范
(2) 自定义槽函数书写规范
(3) 发送信号
(4) 示例
A. 示例一
B. 示例二 —— 老师说“上课了”学生回到座位学习
C. 示例三 —— 老师点击按钮触发学生上课 一、信号和槽概述
事件与信号 在 Qt 中用户与控件的交互如点击按钮或关闭窗口产生事件每个事件触发相应的信号。 信号是事件的通知形式通过函数表示。
响应与槽 控件接收信号并作出响应动作称为槽。槽为普通 C 函数可定义在类的不同访问级别中并能被关联到一个或多个信号上自动执行。 二、本质
1. 信号的本质
信号本质上是事件由用户操作触发通过特定函数形式通知开发者。
例如
按钮单击、双击鼠标移动、鼠标按下、鼠标释放键盘输入 那么在 Qt 中信号是通过什么形式呈现给使用者的呢 我们对哪个窗口进行操作, 哪个窗口就可以捕捉到这些被触发的事件。对于使用者来说触发了一个事件我们就可以得到 Qt 框架给我们发出的某个特定信号。信号的呈现形式就是函数 也就是说某个事件产生了 Qt 框架就会调用某个对应的信号函数通知使用者。 2. 槽的本质
槽是回调函数用于响应信号当关联的信号发射时槽函数会被自动调用。
关于 回调函数
C 语言阶段 - 函数指针
实现转移表降低代码的 “圈复杂度”实现回调函数效果qsort
C 阶段
STL 中函数对象 / 仿函数lambda 表达式
Linux
信号处理函数线程的入口函数epoll 基于回调的机制
底层实现
1. 函数间的相互调用
在Qt框架中信号和槽机制本质上是通过函数间的相互调用来实现的。具体来说
信号函数每个信号都可以用一个函数来表示。例如“按钮被按下”的事件可以用clicked()信号函数来表示。槽函数同样地每个槽也可以用一个函数表示比如“窗口关闭”的动作可以用close()槽函数来表示。
当使用信号和槽机制来实现特定功能时如点击按钮关闭窗口实际上是在连接clicked()信号与close()槽函数使得点击按钮触发clicked()会导致窗口关闭执行close()的效果。
2. 类成员中的特殊角色
信号函数和槽函数通常位于某个类中但它们与普通成员函数相比有一些特别之处
修饰关键字
这些关键字是Qt对C语言的扩展专门用于标识信号和槽函数。 信号函数使用signals关键字进行修饰。槽函数则使用public slots、protected slots或private slots关键字修饰。
声明与定义 信号函数只需要声明而无需定义其定义由Qt自动处理这种自动生成代码的机制称为 “ 元编程 ”Meta Programming这种操作在很多场景中都能见到。槽函数需要像普通函数一样定义和实现因为它们包含了具体的响应逻辑。 三、使用
1. 连接信号和槽
QObject 是 Qt 内置的父类Qt 中提供的很多类都是直接或者间接继承自 QObject。在 Java 中也存在相似的设定使用 QObject::connect() 函数关联信号与槽指定发送者、信号类型、接收者及方法。
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通常不需要手动设定。
示例
在窗口中设置一个按钮当点击 “按钮” 时关闭 “窗口” tip: 2. 查看内置信号和槽
利用 Qt 帮助文档查询系统自带的信号和槽通常在类或其父类中查找。
如上述示例要查询 “按钮” 的信号在帮助文档中输入QPushButton 首先可以在 Contents 中寻找关键字 signals如果没有找到继续去父类中查找因此我们去他的父类 QAbstractButton 中继续查找关键字 signals 这里的 clicked() 就是我们要找的信号。槽函数的寻找方式和信号一样只不过它的关键字是 slot。 3. 通过 Qt Creator 生成代码
Qt Creator 提供可视化界面帮助快速生成信号槽代码简化开发流程。
示例点击按钮关闭窗口
新建项目并创建 UI 文件。在 UI 设计界面添加按钮并配置属性。
可视化生成槽函数 当鼠标单击 “转到槽...” 之后出现如下界面对于按钮来说当点击时发送的信号是clicked()所以此处选择clicked()
这个窗口列出了 QPushButton 给我们提供的所有信号还包含了 QPushButton 父类的信号。 对于普通按钮来说使用 clicked 信号即可。 clicked(bool) 没有意义的具有特殊状态的按钮比如复选按钮才会用到 clicked(bool)。 然后 就会跳转到 Qt Creator 自动生成槽函数原型框架并在槽函数中添加关闭窗口逻辑。 说明自动生成槽函数的名称有一定的规则槽函数的命名规则为on_XXX_SSS其中
以 on 开头中间使用下划线连接起来。XXX 表示的是对象名控件的 objectName 属性。SSS 表示的是对应的信号。
如on_pushButton_clicked() pushButton 代表的是对象名clicked 是对应的信号。按照这种命名风格定义的槽函数就会被 Qt 自动的和对应的信号进行连接。
但是我们日常写代码的时候除非是 IDE 自动生成否则最好还是不要去依赖命名规则而是显式使用 connect 更好。
一方面显式 connect 可以更清晰直观的描述信号和槽的连接关系。另一方面也是防止信号或者槽的名字拼写错误导致连接失效。
当然是配置大于约定还是约定大于配置哪种更好。这样的话题业界尚存在争议这里我个人还是更建议 日常优先考虑显式 connect。 在 widget.cpp 中自动生成槽函数定义 在槽函数函数定义中添加要实现的功能实现关闭窗口的效果 四. 自定义信号和槽
1. 基本语法
在 Qt 中允许开发者自定义信号的发送方及接收方即 可以定义自己的信号函数和槽函数。为了实现这一点必须遵循一定的 书写规范。
Q_OBJECT 宏 在类中使用信号槽机制的前提是类最开始处需要声明Q_OBJECT宏。这个宏展开大量代码使编译器能够识别并处理信号和槽。Qt Creator通常会自动添加此宏。 (1) 自定义信号函数书写规范
规范要点
自定义信号较少见因为Qt内置信号已足够满足大多数需求。信号本质上是特殊的函数仅需声明无需实现返回类型为void。可以有参数并支持重载。必须放在signals关键字下这是Qt扩展的关键字用于标识信号。
构建过程
头文件的 关键字下 定义 qmake工具在构建项目时会扫描到signals关键字并自动生成相应的函数定义。
(2) 自定义槽函数书写规范
操作规程 槽函数的定义与普通成员函数无异但早期版本要求槽函数必须位于public slots、protected slots或private slots下。现代版本允许槽函数放置于public作用域中或全局范围内。返回类型为void需要声明和实现支持参数和重载。
slots 关键字 同样是Qt扩展的关键字用于指示qmake生成相关代码。我们上面有提到过会进行 元编程
(3) 发送信号
使用emit关键字来触发信号。尽管emit是一个空宏且可选但它有助于提醒开发人员当前正在发射信号。
(4) 示例
A. 示例一
在widget.h中声明自定义信号和槽。 在widget.cpp中实现槽函数并连接信号和槽。 运行 B. 示例二 —— 老师说“上课了”学生回到座位学习
创建老师类和学生类分别声明信号和槽。
在源文件中新建两个类一个是老师类一个是学生类首先选中项目名称鼠标右键 —— add new... 注意在 Qt 中新建类时要选择新建类的父类。 显然当前项目中还没有什么类适合做新类的父类同时新的类也不是一个 “窗口” 或者 “控件”这种情况一般选择 QObject 作为基类。这样做的好处是这个新类的对象可以搭配 Qt 的对象树机制便于对象的正确释放。
对于 “学生类” 以上述同样的方式进行添加添加完成之后项目目录新增文件如下 在widget.h中实例化这两个类的对象。 在student.cpp中实现槽函数。 在widget.cpp中连接信号和槽。 运行 C. 示例三 —— 老师点击按钮触发学生上课
实现逻辑同上通过UI中的按钮触发事件。 运行