QT信号槽机制[Qt槽判断信号来源]

365bet手机开户 ⌚ 2025-11-07 23:03:15 👤 admin 👁️ 9675 ❤️ 643
QT信号槽机制[Qt槽判断信号来源]

大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说QT信号槽机制[Qt槽判断信号来源],希望能够帮助大家进步!!!

信号槽信号槽是QT中用于对象间通信的一种机制,也是QT的核心机制。在GUI编程中,我们经常需要在改变一个组件的同时,通知另一个组件做出响应。例如:

一开始我们的Find按钮是未激活的,用户输入要查找的内容后,查找按钮就被激活,这就是输入框与Find按钮这两个组件间通信的例子。

早期,对象间的通信采用回调来实现。回调实际上是利用函数指针来实现,当我们希望某件事发生时处理函数能够获得通知,就需要将回调函数的指针传递给处理函数,这样处理函数就会在合适的时候调用回调函数。回调有两个明显的缺点:

它们不是类型安全的,我们无法保证处理函数传递给回调函数的参数都是正确的。回调函数和处理函数紧密耦合,源于处理函数必须知道哪一个函数被回调。信号与槽在QT中,我们有回调技术之外的选择,也即是信号槽机制。所谓的信号与槽,其实都是函数。当特定事件被触发时(如在输入框输入了字符)将发送一个信号,而与该信号建立的连接槽,则可以接收到该信号并做出反应(激活Find按钮)。

QT组件预定义了很多信号和槽,而在GUI编程中,我们习惯于继承那些组件,继承后添加我们自己的槽,以便以我们的方式来处理信号。槽和普通的C++成员函数几乎是一样的,它可以是虚函数,可以被重载,可以是共有、私有或是保护的,也同样可以被其他成员函数调用。它的函数参数也可以是任意类型的。唯一不同的是:槽还可以和信号连接在一起。

与回调不同,信号槽机制是类型安全的。这体现在信号的函数签名与槽的函数签名必须匹配上,才能够发生信号的传递。实际上,槽的参数个数可以比信号的参数个数少,因为槽能够忽略信号形参中多出来的参数。信号和槽是松耦合的:发出信号的类不关心哪些类将接收它的信号。QT的信号槽机制吧哦这里在正确的时间,槽能够接收到信号的参数并调用。信号和槽都可以有任意个数的参数,它们都是类型安全的。

自定义信号和槽的一个例子首先我们要知道的是,所有继承自QObject或者它的子类(如QWidget)都可以包含信号槽。我们写的类须继承自QObject(或其子类)。所有包含了信号槽的类都必须在声明的上部含有Q_OBJECT宏。

一个基于QObject的C++简单类:

代码语言:javascript复制//MyStr.h

# ifndef MYSTR

# define MYSTR

#include

#include

class MyStr :public QObject

{

Q_OBJECT //必须包含的宏

public:

MyStr (){m_value = "zero";}

QString value() const {return m_value;}

public slots :

void setValue(QString value );

signals: //信号

void valueChanged(QString newValue);

private:

QString m_value;

};

#endif 只听到从架构师办公室传来架构君的声音:

新酒又添残酒困。有谁来对上联或下联?

在这个简单的类中,我们可以看到,使用slots来表示槽,而使用signals来表示信号。实际上没有那么神秘,它们都是宏定义,甚至signals只是public的宏定义:代码语言:javascript复制# define signals publicSignal的代码会由 moc 自动生成,开发人员一定不能在自己的C++代码中实现它。反之,槽应该由编程人员来实现,下面提供MyStr::setVaule()的一种可能实现代码语言:javascript复制#include"MyStr.h"

void MyStr::setValue(QString value)

{

if(value != m_value)

{

m_value = value;

emit valueChanged(value);

}

}setValue函数首先比较新参的值与数据成员的值是否是一样的(后面有解释为何这样做),如果不是,则设置好数据成员m_value的值,然后,把信号valueChanged()发送出去。发送给谁?类并没有写,这并不是类设计者所关心的,也不是类所关心的,它只管把信号发送出去就行。然后,我们再来设置谁来接收这个信号。

代码语言:javascript复制int main(int argc, char *argv[])

{

MyStr a;

MyStr b;

QObject::connect(&a,SIGNAL(valueChanged(QString)),&b,SLOT(setValue(QString)));

a.setValue("this is A");

return 0;

}我们定义了两个类对象a/b,使用 QObject::connect()函数指定了发送方、信号、接收方、槽等信息,connect函数的格式如下:

代码语言:javascript复制 QObject::connect( 发送方, SIGNAL(...), 接收方, SLOT(..) );当我们调用a的成员函数setValue时,该函数除了把a.m_value设置为"this is A",也把信号valueChanged()发送出去,被b.setValue所接收,从而,把b.m_value设置为"this is A",同时b.setValue又把valueChanged信号发射出去,然而该信号并没有对象接收,因为我们没有建立以b为发送方的任何连接。此时你应该明白,为何在emit前需要判断value != m_value,因为如果没有此步骤,且恰巧设置了

QObject::connect(&b,SIGNAL(valueChanged(QString)),&a,SLOT(setValue(QString)));

则b的信号被a接收,a又发送信号被b接收,如此进入死循环。

代码语言:javascript复制int main(int argc, char *argv[])

{

QApplication app(argc, argv);

MyStr a;

MyStr b;

QObject::connect(&a,SIGNAL(valueChanged(QString)),&b,SLOT(setValue(QString)));

a.setValue("this is A");

QLabel* label = new QLabel;

label->setText( b.value());

label->show();

return app.exec();

}我们使用label输出来看看b是否接收到a的信号,如果是,则b的内容应该是"this is A",输出在label上,程序运行结果:

这个例子展示了对象之间通信的一种方式。对象间可以一起工作,而不需要知道彼此的任何信息。为了达到通信的目的,只需要将它们连接起来,而这只需要通过 调用 QObject::connect() 函数指定一些简单信息就好。

细节连接要把信号成功连接到槽,它们的参数必须具有相同的顺序和相同的类型,或者允许信号的参数比槽多,槽会自动忽略掉多出来的参数而进行调用。

一个信号可以连接多个槽使用QObject::connect可以把一个信号连接到多个槽,而当信号发射时,将按声明联系时的顺序依次调用槽。

代码语言:javascript复制 MyStr a;

MyStr b;

MyStr c;

//信号连接到两个槽

QObject::connect(&a,SIGNAL(valueChanged(QString)),&b,SLOT(setValue(QString)));

QObject::connect(&a,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));

a.setValue("this is A");

//依次调用b.setValue()、c.setValue()多个信号可以连接同一个槽同样的,可以让多个信号连接到同一个槽上 ,而且其中的每一个信号的发送,都会调用了那个槽。

代码语言:javascript复制 MyStr a;

MyStr b;

MyStr c;

//两个信号连接到同一个槽

QObject::connect(&a,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));

QObject::connect(&b,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));

//下面的操作皆会调用到槽c.setValue()

a.setValue("this is A");

b.setValue("this is B");一个信号可以和另外一个信号相连接当发射第一个信号的时候,也会把第二个信号一个发送出去。

代码语言:javascript复制 MyStr a;

MyStr b;

MyStr c;

//两个信号相连接

QObject::connect(&a,SIGNAL(valueChanged(QString)),&b,SIGNAL(valueChanged(QString)));

//再建立b与c的连接

QObject::connect(&b,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));

//下面的操作同时发送了信号a.valueChanged与b.valueChanged

a.setValue("this is A");

//从而信号b.valueChanged被槽c.setValue所接收连接可以被移除代码语言:javascript复制//移除b 与 c之间的连接

QObject::disconnect(&b,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));实际上当对象被delete时,其关联的所有链接都会失效,QT会自动移除和这个对象的所有链接。

完感谢您耐心的阅读。

今天文章到此就结束了,感谢您的阅读,Java架构师必看祝您升职加薪,年年好运。

相关数据

电竞行业学历指南:从职业选手到管理精英的多元路径

电竞行业学历指南:从职业选手到管理精英的多元路径

 一、电竞行业:学历门槛最宽松的领域之一 电竞行业可能是当今对学历背景最包容的领域之一。与金融、医疗等传统行业不同,电竞的核心

10-15 365bet娱乐平台官网
新一代北斗户户通安装流程详细图解出炉

新一代北斗户户通安装流程详细图解出炉

新一代北斗户户通——卫星直播系统综合接收解码器(智能基本型—卫星地面双模)安装流程图解完整版: 1.安装流程启动前示意图 2.安装启动

08-06 365bet娱乐平台官网
两兄弟的对决 帕萨特和朗逸的全面对比

两兄弟的对决 帕萨特和朗逸的全面对比

虽然现在汽车保有量越来越高,新车市场的销售不再像过往几年那么的火爆,但新车的推出包括全新车型以及换代车型,其速度依旧不减,今天

09-04 365赌博是什么意思
it项目管理风险类型有哪些

it项目管理风险类型有哪些

IT项目管理风险类型有哪些 IT项目管理中常见的风险类型包括:需求变化风险、技术风险、时间风险、成本风险、资源风险、质量风险、沟通风

07-14 365赌博是什么意思
怎么删除抖音视频

怎么删除抖音视频

在抖音平台上,用户经常需要管理自己的视频作品,删除不再需要或不想保留的内容。以下是详细的步骤和注意事项,帮助用户高效、安全地删

07-01 365赌博是什么意思
如何在优酷上顺利退出登录账号的详细步骤

如何在优酷上顺利退出登录账号的详细步骤

系统可能会要求你确认是否退出。确认后,你的账户将被成功注销。 三、在电视端退出登录 (Logging Out on the TV Version) 1. 打开优酷电视应用 (Open th

08-19 365赌博是什么意思