目录
1.信号源、信号和槽:
2.Qt类的继承关系:
3.自定义槽函数:
4.第一种信号和槽的连接的方法:
5.第二种信号和槽的连接的方法:
6.自定义信号:
7.发射信号:
8.信号和槽的传参:
9.信号和槽的意义:
10.断开信号和槽的连接:
11.槽函数和lambda表达式:
1.信号源、信号和槽:
- 信号源(Sender):发出信号的对象。
- 信号(Signal):由对象发出,用于通知某个事件的发生。用户进行不同的个操作,会触发不同的信号,比如点击按钮,勾选选择框等
- 槽(Slot):一个函数,可以连接到信号。当信号发出时,连接到该信号的槽会被调用
2.Qt类的继承关系:
- QObject 是所有Qt对象的基类,提供信号槽、事件处理等基础功能。
- QWidget 是所有用户界面对象的基类,继承自 QObject,提供窗口部件的绘制、事件处理等功能。
- 各种小控件(如 QPushButton, QLabel, QLineEdit 等)都继承自 QWidget,从而拥有用户界面的功能。
3.自定义槽函数:
- 槽函数的有两种定义方式:
- 第一种:先在widget对象中声明,然后在.cpp文件中定义。
- 第二种:使用拖拽的方式创建控件,创建好后在ui界面,右键点击要添加槽函数的控件,会出现一个菜单,选择转到槽,就能够看到可以定义的所有槽函数,选择之后,会自动生成槽函数的声明和定义的框架。
- 第一种方法自定义的槽函数,要使用connect手动进行连接信号,但是第二种自动生成槽函数,我们发现头文件和槽函数源文件中都没有生成connect连接。
4.第一种信号和槽的连接的方法:
- 要使信号和槽连接起来。通常使用QObject::connect函数进行连接:
- 旧版本的conncect函数,格式为:
connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection);
- 其中的前四个参数分别代表:发出信号的对象、信号的类型的函数指针、接收信号并执行槽函数的对象、槽函数的函数指针。
- 旧版本的connect函数,传参时,需要将函数指针转换为char*类型,需要用到两个宏函数:SIGNAL和SIGNAL,来分别将connect的第二和第四个参数转换为char*类型。
- 从Qt5开始,使用了模板进行泛型编程,就可以不在使用两个宏来转换指针类型,可以直接传递函数指针了。
5.第二种信号和槽的连接的方法:
- 利用特定的命名规则来命名槽函数,自动连接信号和槽。
- 因为通过拖拽的方式生成的每一个控件都有唯一的objectname,通过这个唯一的objectname以一定的格式,来命名槽函数,就可以建立信号和槽之间的关联。具体的命名规则如下:
void on_<object name>_<signal name>(<signal parameters>);
- <object name> 是发出信号的对象的名称(对象的 objectName 属性)。<signal name> 是信号的名称。
- 例如,如果有一个按钮对象,其 objectName 是 myButton,并且要自动连接它的 clicked() 信号到某个槽函数,那么槽函数的名称应为:void on_myButton_clicked();
- 当有槽函数的名称符合上述命名规则,qt就会触发自动连接信号和槽的规则。
- 如果通过拖拽的方式创建控件,建议使用自动连接信号和槽。
- 如果手动创建控件,还是使用connect建立连接。
- Qt 的自动连接机制主要通过 connectSlotsByName 函数实现。这个函数会根据对象的 objectName 属性和槽函数的名称进行匹配,从而自动连接信号和槽。也可以在手动调用该函数的情况下,不使用connect。
6.自定义信号:
- 用户可以进行的操作,是可以穷举的,Qt的内置信号基本可以覆盖用户的所有可能的操作。所以很少会用到自定义信号。
- 在 Qt 中,自定义信号是一个没有函数体的函数声明。程序员只需声明信号即可,这个函数的定义是由 Qt 在编译过程中自动生成的,程序员无法干预信号函数的具体实现。
- 信号函数的返回值必须是void。信号函数可以有参数,也可以没有参数。支持函数重载。
- 声明信号,要加上signal,就像声明一个函数为public一样,当Qt扫描到signal时,就会默认下面的函数声明当作信号,并且给这些信号函数自动生成函数的定义。
signals: void customSignal(int value); // 自定义信号
7.发射信号:
- Qt的内置信号,无需手动触发,但是自定义信号,需要手动触发。
- 发射信号需要使用emit关键字,emit+信号函数的调用就可以实现信号的发送。
- 比如一个叫mySignal的自定义信号,要发送这个信号就可以:emit mySignal();
- 在Qt5中,不写emit直接调用信号函数也可以发送信号,但是加上emit可以提高代码的可读性。还是加上吧。
8.信号和槽的传参:
- 信号和槽,都可以带参数,当信号带有参数时,槽的参数必须和信号的参数一致。
- 当带参的信号被发送出去,被对应的槽函数接收后,就能够达到让信号给槽传参的效果了。
- 信号和槽的参数数量可以不一致,但是类型必须一致,要求信号的参数大于等于槽的参数数量。
- 在Qt中,如果想要一个类能够使用信号槽,就需要在类的开始加上Q_Object。
9.信号和槽的意义:
- 信号和槽要解决的问题,就是响应用户的操作。
- Qt搞一个单独的connect完成信号和槽的连接,有两点设想,其一是把控件和用户逻辑解耦合,其二是实现多对多的效果,可以一个信号绑定多个槽,也可以一个槽绑定多个信号。
- 实际上,多对多是一个伪需求,实际开发中一对一就足够使用了。
10.断开信号和槽的连接:
- 使用disconnect可以断开信号和槽的连接,使用方法和connect非常相似,一般来说很少主动断开,当要将信号重新绑定到另一个槽上时,才会用到断开。
- 传递参数和connect一样。
11.槽函数和lambda表达式:
- 在 Qt 中,可以使用 lambda 表达式来定义和连接槽函数。使用 lambda 表达式作为槽函数的好处是可以直接在 connect 调用中编写逻辑,避免为简单的操作单独定义槽函数。类似于匿名函数。
- connect的第四个参数,是由三组括号构成:[ ]( ){ }。
- 第一对括号可以用于变量捕获,Lambda 表达式的变量捕获机制允许在 lambda 表达式内部访问外部作用域中的变量。
connect(button, &QPushButton::clicked, this, [this, count]() mutable {count++;});
- 第二对括号,传递参数;第三对括号,实现逻辑。