Qt:信号定义及调用

本文详细介绍了Qt中的信号机制,包括信号如何作为函数声明、元对象系统在信号实现中的作用,以及如何通过emit宏发送信号、信号与槽函数的绑定和事件处理流程。特别强调了在多线程环境下处理UI控件时的注意事项。
摘要由CSDN通过智能技术生成

Qt的信号本质是函数,且默认也只能为公有函数(这样可以在任何地方进行信号发送)

前置条件

Qt的信号支持需要Qt的元对象系统的支持,元对象系统需要一下条件

  1. 类必须继承与QObject
  2. 类内必须私有声明Q_OBJECT宏
  3. 需有元对象编译器(moc)

声明和实现

在我们定义的元对象类中可以进行信号的声明,默认形式为 :

void mySignal(paramterLists);//返回值只能是void

在我们的代码中,我们只能声明信号,而不能为信号编写实现代码。实际的信号实现是由元对象系统自动生成的。

当我们的.cpp文件被编译时,如果在类的声明中包含了Q_OBJECT宏,编译器会使用元对象编译器(MOC)来创建一个新的.cpp源文件,该源文件以moc_开头。这个新生成的源文件将参与编译和链接过程,并包含信号的实现代码。

元对象编译器会根据类的声明中的信号定义信息,自动生成信号的实现代码。这些实现代码包括信号的触发、连接和处理逻辑等。生成的源文件会在编译过程中被编译为目标代码,并与其他源文件一起链接到最终的可执行文件中。

通过这种方式,我们可以在代码中声明信号,而不需要手动编写信号的实现代码。元对象系统会负责自动生成并处理信号的实现,使我们能够方便地使用信号和槽机制来实现事件驱动的功能。

例如下面的函数,就是自动生成的文件moc_myTest.cpp中的信号定义。

void PlotsPanel::show_a_text_message(QString _t1)
{
    void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
    QMetaObject::activate(this, &staticMetaObject, 6, _a);
}

调用

在实际的代码中,我们可以使用emit宏进行调用,即使实际的代码中emit宏定义是一个空的,我们还是要写上,这样别人看到就可以立即知道这事一个信号发送的调用。
下面是Qt中emit宏的定义

#ifndef QT_NO_EMIT
# define emit
#endif

我们可以使用下面两种形式发送信号:

	emit(mySignal(paramterLists));
	//或者
	emit mySignal(paramterLists);

上面两种形式最终经过预编译,都会变成一样的

mySignal(paramterLists)

运行

QT程序只有一个应用程序类QApplication,QApplication也只有一个事件处理函数exex(),我们整个程序的运行期间都是在不断的QApplication的exex()函数。

从名字就可以知道exex是进行事件处理的函数,但它同样可以处理信号,信号被发送后会被放入到事件队列中,但它不是一个事件。

exex()函数内部从事件队列中取出信号,会根据信号和槽的绑定形式来调用对应的槽函数,如果是直接绑定,这槽函会直接在exec()函数内部执行,如果不是且为多线程,这槽函数会进入另一个线程中运行。

此时注意我们需要避免任何操作界面的操作放在非主线程中运行,这样会大概率导致两个线程同时访问UI控件资源而崩溃

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值