Qt的signal和slot是同步的,还是异步的

Qt的signal和slot是同步的,还是异步的,第1张

我们知道Qt以他的signal和slot机制独步天下。但大家在用的时候有没有注意过,signal和slot是异步的,还是同步的呢?为此我问过不少Qt的使用者,有人说是同步的,有人说是异步的,也有人说着要看Qt的当时心情了¥%&

其实是异步还是同步,是用户决定的。如果大家仔细看过connect函数的介绍就知道,connect最后的有一个参数Qt::ConnectionType type 他将决定是异步还是同步(具体的类型可以参见帮助)。只不过平常我们使用的时候,他默认成了Qt::AutoConnection。有的兄台看到这里的时候,就会问,啥是Auto模式。其实Auto模式,就是看Qt的心情来决定是异步还是同步。而决定这个心情的就是,sender和receiver的他们分别所处的线程。如果是同一线程则就是同步调用,如果不在同一线程就是异步调用。

但真相果真如此吗?正像青春永驻的柯南君所指出的,真相永远都隐藏在表面之下。

请各位看官思考以下案例:

class A : public QObject

qheadviewsort是Qt中的一个类,用于实现表头的排序功能。如果想要更改qheadviewsort图标,可以通过修改表头中的排序箭头图标来实现。具体步骤如下:

1 打开Qt Creator,找到需要修改的表格控件的ui文件。

2 在该文件中找到表格控件的表头,并将鼠标放置在表头上。

3 点击表头右侧的“小箭头”,选择“Edit Items”。

4 在d出的“Edit Items”对话框中,找到需要修改的列,并在该列的“Header”字段中输入自定义的表头名称。

5 在该列的“Sort Indicator”字段中,可以选择不同的排序箭头图标。如果想要更改图标,可以点击“”按钮选择新的图标文件。

6 最后,点击“OK”按钮保存修改。

需要注意的是,更改qheadviewsort图标的方法可能因Qt版本不同而有所差异。在实际应用中,可以根据具体的情况进行调整。

拓展内容:Qt Creator是一个跨平台的集成开发环境,用于开发Qt应用程序。它提供了丰富的图形化界面设计工具和代码编辑器,方便开发人员快速创建高质量的Qt应用程序。在Qt Creator中,可以通过简单的拖放 *** 作和可视化界面设计工具,快速创建复杂的用户界面,并且可以轻松集成各种第三方库和插件,扩展应用程序的功能。

一、信号槽的基本概念

关于QT信号槽的基本概念大家都懂,通过信号槽机制,QT使对象间的通信变得非常简单:

A对象声明信号(signal),B对象实现与之参数相匹配的槽(slot),通过调用connect进行连接,合适的时机A对象使用emit把信号带上参数发射出去,B对象的槽会就接收到响应。

信号槽机制有一些特点:

1 类型安全:只有参数匹配的信号与槽才可以连接成功(信号的参数可以更多,槽会忽略多余的参数)。

2 线程安全:通过借助QT自已的事件机制,信号槽支持跨线程并且可以保证线程安全。

3 松耦合:信号不关心有哪些或者多少个对象与之连接;槽不关心自己连接了哪些对象的哪些信号。这些都不会影响何时发出信号或者信号如何处理。

4 信号与槽是多对多的关系:一个信号可以连接多个槽,一个槽也可以用来接收多个信号。

使用这套机制,类需要继承QObject并在类中声明Q_OBJECT。下面就对信号槽的实现做一些剖析,了解了这些在使用的时候就不会踩坑喽。

二、信号与槽的定义

槽:用来接收信号,可以被看作是普通成员函数,可以被直接调用。支持public,protected,private修饰,用来定义可以调用连接到此槽的范围。

1 public slots:

2 void testslot(const QString& strSeqId);

信号:只需要声明信号名与参数列表即可,就像是一个只有声明没有实现的成员函数。

1 signals:

2 void testsignal(const QString&);

QT会在moc的cpp文件中实现它(参考下面代码)。下面代码中调用activate的第三个参数是类中信号的序列号。

1 // SIGNAL 0

2 void CTestObject:: testsignal (const QString & _t1)

3 {

4 void _a[] = { 0, const_cast<void>(reinterpret_cast<const void>(&_t1)) };

5 QMetaObject::activate(this, &staticMetaObject, 0, _a);

6 }

三、信号槽的连接与触发

通过调用connect()函数建立连接,会把连接信息保存在sender对象中;调用desconnect()函数来取消。

connect函数的最后一个参数来用指定连接类型(因为有默认,我们一般不填写),后面会再提到它。

1 static bool connect(const QObject sender, const QMetaMethod &signal,

2 const QObject receiver, const QMetaMethod &method,

3 Qt::ConnectionType type = Qt::AutoConnection);

一切就绪,发射!在sender对象中调用:

1 emit testsignal(“test”);

1 # define emit

上面代码可以看到emit被定义为空,这样在发射信号时就相当于直接调用QT为我们moc出来的函数testsignal(constQString & _t1)。

具体的 *** 作由QMetaObject::activate()来处理:遍历所有receiver并触发它们的slots。针对不同的连接类型,这里的派发逻辑会有不同。

更多信息请参阅:

http://blogcsdnnet/harbinzju/article/details/10813635

Ticker(QWidgetparent=0);//为什么在括号内要有(QWidgetparent=0)?这是构造函数的参数。C++可以使用默认参数。其实写成iQWidgetparent=NULL;就是没有父窗口,就更容易理解了。voidpaintEvent(QPaintEventevent);//(QPaintEventevent)又是什么意思?定义了event一个指针?如果说定义一个event指针那为什么下面三句又定义了event指针?你这么问,应该是基础不好,C/C++的参数名是任意的,只要符合语法要求就可以,因此是可以相同的,这个只是函数的参数,而不是定义变量。三个event指针,是三个不同类型的事件指针,是三个函数的参数,不是定义变量。Ticker::Ticker(QWidgetparent):QWidget(parent)//前一个ticker指的是类,第二个ticker是成员函数还是?,那后面的两个括号内指的是什么第二个是构造函数,Ticker(QWidgetparent)是构造函数,QWidgetparent是构造函数的参数;:QWidget(parent)是初始化列表的格式,你可以搜索一下初始化列表来查一下更具体的内容。voidTicker::showEvent(QShowEvent/event/)//定义类和成员函数括号内又是干什么的?是否可以将QShowEvent换成QShowEventevent?可以,函数定义的时候,是可以写参数,也可以不写,只简写参数的类型。QWidget::timerEvent(event);//调用类和成员函数括号内event怎么又没有号了?感觉你的基础真的不好,函数定义的时候,参数是要写类型的,所以那个是表示指针类型。而函数调用的时候,参数是指针类型的,就可以直接使用啊。如果不是指针,就用取地址符号(&)转成地址(指针就是地址)。voidpaintEvent(QPaintEventevent);//这样是定义,其实这么写更好一些voidpaintEvent(QPaintEventevent);//这个函数的参数是event,event的类型是QPaintEvent。感觉你的理解是这个函数的参数时event,而参数类型是QPaintEvent,那样就错了。不知道你明白没有。给你一些建议,因为你的基础看起来不是很好,建议看看谭浩强的《C++程序设计》等你完全理解这些问题了,再看看钱能的《C++程序设计》。再看国外的经典书。基础很重要,很重要。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/12188548.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存