小型教育网站的开发与建设系统,qq浏览器直接打开网页,wordpress大气企业主题,网站登不上去的原因目录
一#xff0c;基本概念
二#xff0c;connect函数使用
2.1 connect
2.2 Qt内置信号和槽 2.3 一些细节
三#xff0c;自定义信号和槽
3.1 自定义槽函数
3.2 自定义信号
3.3 带参数的信号槽
四#xff0c;信号和槽的意义
五#xff0c;信号和槽断开连接
六基本概念
二connect函数使用
2.1 connect
2.2 Qt内置信号和槽 2.3 一些细节
三自定义信号和槽
3.1 自定义槽函数
3.2 自定义信号
3.3 带参数的信号槽
四信号和槽的意义
五信号和槽断开连接
六使用lamdba表达式定义槽函数 一基本概念
Qt中用户和空间的每次交互过程我们称为一个事件比如“点击按钮”和“关闭窗口”都是一个事件每个事件发生时都会产生一个信号比如点击按钮会产生“按钮被点击的信号”用户关闭窗口会产生“窗口被关闭”的信号这点我们前面已经介绍过并且基本概念和Linux的信号有相似之处Linux系统编程——进程信号-CSDN博客 在Qt中的信号主要涉及到三个要素
信号源由哪个空间发出信号类型用户进行不同的操作就可能触发不同的信号信号的处理方式就是一个处理函数这个处理函数在Qt中就叫做“槽函数”slot其实就是一个回调函数Qt 可以用connect将一个信号和一个槽关联起来
注意必须先把信号和槽用connect关联之后再触发这个信号才会执行槽函数顺序不能颠倒
二connect函数使用
2.1 connect
这个函数是 QObject 类提供的一个静态成员函数 问题为什么说是静态呢 解答 这个QObject 类是其它Qt内置类的“祖宗”因为Qt的内置类有很多很多继承关系的而绝大多数的类往上深扒继承关系最终都会看到有个 QObject类所以在很多很多Qt内置内中都可以直接使用connect这个函数 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跨平台应用程序开发框架2—— 初识QT-CSDN博客
上下面我们实现下点击按钮关闭窗口的代码 这个close也是别人已经实现好了作用就是关闭窗口我们直接用就行 注意我们在填第二个参数时会显示有两个click 第一个click左边小图标是锯齿的表示这是一个slot函数作用就是在调用的时候相当于点了一下按钮第二个clicked左边的是一个类似信号发射器的一个图标这个表示信号我们要选的是第二个clicked表示过去式就是“点完了” 2.2 Qt内置信号和槽
Qt 也提供了很多内置的信号和槽让我们使用但是要想全部记住几乎是不可能的所以最好的方式就是多看文档多写所谓“熟能生巧”
在翻文档的时候如果没有找到对应的条目可以看看这个类的父类并且文档也提供了这个类的父类叫什么以QPushButton为例
关于这个QAbstractButton类首先 abstract 这个单词是“抽象的”的意思因为Qt会提供好几种按钮这些按钮 中存在一些功能相同的内容所以就把这些相同的对东西搞出来单独搞成了一个QAbstractButton这个类其它很多控件类也是如此的 然后往下滑就会看到一些内置的slot和signal如果没有就可以去父类看看比如上面说到的QAbstractButton类在它的页面往下滑就可以看到 再点击对应的绿色的就能看到更多详细信息比如clicked 2.3 一些细节
我们再观察下connect函数的定义和使用 问题char* 和 函数指针是一个东西吗 解答 两个都是指针但是不是同一个类型的指针 我们clicked函数的声明是所以指向这个函数的函数指针也就是取地址后的指针就是 void(*)()这个和char*是完全不同的close同理而在C中是不允许用两个不同类型的指针类型相互赋值的函数传参本质上就是赋值 我们可以看下connect在文档中的声明 这个函数声明是旧版本的Qt的connect的声明所以在以前版本的传参和现在有区别
给信号参数传参时要搭配一个 SIGNAL 宏主要是将传入的函数指针转成 char*给槽函数传参时要搭配一个 SLOT 宏同上
所以旧版本需要进行的用法如下
connect(button, SIGNAL(QPushButton::clicked), this, SLOT(Widget::close));
在Qt 5 开始对上述操作进行了简化去掉了两个宏给connect提供了重载版本第二个参数和第四个参数乘客泛型参数允许传入任意类型的函数指针 这个就是Qt封装的一个类型萃取器但是关于类型萃取涉及模板特化等特性这里不过多展开
有了泛型参数此时这个connect函数就带有了一定的“参数检查”功能如果传入的第一和第二或者第三和第四参数不匹配那么代码就会直接编译出错这个是宏做不到或者说很难做到的
三自定义信号和槽
3.1 自定义槽函数
有时候Qt内置的信号和槽可能无法满足我们的需求所以我们可以自己实现信号和槽我们先说自定义槽
我们上篇文章已经用自定义槽实现了按按钮切换按钮里的文本 所以所谓的槽函数操作过程和自定义一个普通的成员函数没啥区别 除了上面这种最基础的还有第二种更便捷的方法
先通过拖拽方式创建一个按钮右键这个按钮点击“转到槽” 比如我实现一个切换窗口标题的按钮 可以看到我们通过这种方式生成的槽函数并没有通过connect关联因为在 Qt 中除了通过connect 之外还可以通过函数名字的方式来自动连接比如上面的槽函数名字 on_pushButton_clicked on相当于固定前缀中间的 pushButton 是按钮的 objectName 后面的 clicked 就是信号的名字所以当函数名符合上述规则之后Qt就能自动把信号和槽进行关联 问题如何做到自动识别的 解答我们把上面槽函数的声明和定义的clicked都换成click再次执行程序可以看到输出有个 而这个函数正是在 ui_widget.h 中调用的 3.2 自定义信号
自定义槽函数非常重要开发中大部分情况都是需要自定义槽函数的因为槽函数就是用户触发某个操作之后要进行的业务逻辑而业务逻辑通常是很复杂的所以需要程序员自己去写而对于自定义信号就比较少见实际开发中很少会需要自定义信号因为信号对应着用户的某个操作而在GUI中用户能进行的操作是可以穷举的Qt 内置的信号基本已经覆盖到了所有的用户操作
因此使用Qt 的内置信号足以应付大部分的开发场景了咱们的Widget虽然还没有定义任何信号但是由于其继承了 QWidget 和 QBbject 这里面已经提供了一些信号可以直接用
但毕竟是大部分那还有一小部分是内置信号解决不了的所以Qt还是为我们提供了自定义信号的途径和方式 所谓 Qt 的信号其实也是一个“函数”槽函数和普通成员之间没啥差别但是信号函数则是一类非常特殊的函数程序员只要写出函数声明并告诉 Qt 这是一个“信号”即可这个函数的定义是 Qt 在编译过程中自动生成的并且这个过程我们无法干预
信号在 Qt 中是特殊的机制Qt 生成的信号函数的实现要配合 Qt 框架做很多既定的操作
然后关于信号函数声明
信号函数的返回值必须是void有没有参数都可以甚至支持重载 在进行自定义信号创建之前要明白几点
Qt 中内置的信号都不需要通过咱们手动通过代码来触发用户在 GUI 进行操作时就会自动触发对应信号发射信号的代码已经内置到 Qt 源码框架中了 而对于我们的自定义信号Qt 有个日俄欧美人你提供了一个关键字 emit 也有发射的意思具体用法下面代码会有演示 ①首先是声明信号函数 ②然后将自定义信号和自定义槽函数关联起来并使用emit关键字手动触发信号 ③查看结果 emit手动触发信号的步骤可以在代码的任意位置不一定非得在构造函数中 其实在 Qt 5 版本之后emit现在其实啥也没干真正的操作都包含在 mySignal 内部生成的函数定义中就是上面的代码中不写emit就写个mySignal() 相当于调用这个函数一样可以完成触发信号但即使如此实际开发中建议加上emit能增加代码可读性标识这个语句是发射信号emit也可以手动发射Qt内置的信号 3.3 带参数的信号槽
信号和槽可以带参数当信号带有参数的时候槽的参数必须和信号的一致此时发射信号的时候就可以给信号函数传递实参与之对应的这个参数就会被传递到对应的槽函数中就可以起到让信号给槽传参效果了 ①先在声明处带上参数C中形参的名字可以省略 ②给槽的定义带上参数 ③查看结果 ④也可以通过按钮来切换标题 //通过拖拽方式创建按钮后右键“转到槽”
void Widget::on_pushButton_clicked()
{emit mySignal(把标题设置为标题1);
}void Widget::on_pushButton_2_clicked()
{emit mySignal(把标题设置为标题2);
}Qt中很多内置的信号也是带有参数的但是这些参数不是我们自己传的比如 clicked 信号就有一个参数是bool表示当前按钮是否处于“选中”状态对于QPushButton没啥作用对QCheckBox复选框很有用后期再讲信号函数的参数和槽参数数量可以不一致但是信号参数数量需要 槽的参数否则会编译报错 问题为什么允许信号参数数量 槽参数个数 呢 解答 一个槽函数可能会绑定多个信号如果我们严格要求参数个数一致就意味着信号绑定槽的要求变高了会有很多麻烦换而言之当下的规则就允许一个槽函数能够绑定更多的信号了 个数不一致槽函数就会按照信号的参数顺序拿到信号的前 N 个参数总之就是要确保槽函数的每个参数是有值的 四信号和槽的意义
信号和槽的主要面对的问题就是“响应”用户的操作执行一段业务逻辑代码
Qt 的这种信号和槽在各类 GUI 开发的框架中是一个比较有特色的存在这个有特色其实是贬义词因为其它的 GUI 开发框架搞的方式更简洁一些网页开发中响应用户操作主要就是挂“回调函数”直接将函数赋值给对应的属性不需要搞一个单独的connect完成上述的信号槽关联大部分的 GUI 开发框架都是这样搞的
Qt 这样的信号槽和connect机制设想是这样的
解耦合把触发用户操作的控件 和 对应的处理逻辑进行解耦合“多对多”效果比如一个信号可以 connect 到多个槽函数上一个槽函数也可以被多个信号 connect
其实在GUI开发过程中“多对多”其实是个伪需求实际开发很少用到绝大多数情况“一对一”够用了而且新推出的一些图形化开发框架很少有再继续支持这种多对多了
五信号和槽断开连接
有连接就有断开假设我们不再继续保持一个信号和槽的连接那么可以使用 disconnect 函数来取消关联
但是disconnect用的是比较少的大部分情况下把信号和槽连上之后就不必再管了主动断开的场景往往是把信号重新绑定到另一个槽函数上
disconnect的用法和connect基本一致 六使用lamdba表达式定义槽函数
定义槽函数时也可以用lamdba表达式的lamdba表达式主要应用在“回调函数”场景中C —— C11新增语法-CSDN博客
废话不多说直接上代码 另外我们也要确认捕获到 lamdba 内部的变量是有意义的因为回调函数的执行时机是不确定的所以就要保证无论用户点击了按钮捕获到的变量都能正确使用lamdba 除了可以按照值得方式来捕获变量[]也可以按照引用得方式来捕获[]这时捕获到的一般就是各种控件的指针但是Qt一般不用[]因为可能会有很多意想不到的报错以上面的代码为例如果是[]那么运行后点击按钮就会报错因为我们在构造函数里创建的button声明周期是随构造函数的构造函数执行完后button就没了这时候传递给lamdba的引用就是个空引用直接闪退lamdba是C11加入的Qt 5 及更高版本默认就是按照C11来编译的如果使用Qt 4 或者更老版本就需要在 .pro 文件里手动加上 C11的编译选项哦