0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

QObject中常使用的成員函數(shù)和重要宏定義

嵌入式小生 ? 來源:嵌入式小生 ? 2023-02-20 09:42 ? 次閱讀

一、QObject的重要知識

QObject是Qt對象模型的核心。這個模型的核心特性是一個強(qiáng)大的無縫對象通信機(jī)制,即信號和槽??梢允褂?code style="font-size:14px;padding:2px 4px;margin-right:2px;margin-left:2px;background-color:rgba(27,31,35,.05);font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(239,112,96);">connect()將信號連接到槽函數(shù),并使用disconnect()破壞已經(jīng)存在的連接。為了避免永不結(jié)束的通知循環(huán),可以使用blockSignals()暫時阻塞信號。受保護(hù)的函數(shù)connectNotify()disconnectNotify()可以用于跟蹤信號連接。

Qt中,以QObject為基礎(chǔ)形成了一棵“對象樹”,當(dāng)使用另一個對象作為父對象創(chuàng)建QObject時,該對象將自動將自己添加到父對象的children()列表中。此后父對象擁有該對象的所有權(quán),則會自動刪除析構(gòu)函數(shù)中的子元素。在開發(fā)中可以使用findChild()findChildren()根據(jù)名稱和可選的類型查找子對象。

每個對象都有一個objectName(),可以通過相應(yīng)的metaObject()找到它的類名(函數(shù):QMetaObject::className())。在實(shí)際開發(fā)中可以使用inherits()函數(shù)確定對象的類是否繼承了QObject繼承層次結(jié)構(gòu)中的另一個類。當(dāng)一個對象被刪除時,會發(fā)出destroyed()信號,通過這一點(diǎn)可以捕獲此信號,避免對QObject進(jìn)行懸掛引用。

二、QObject重要成員函數(shù)

本小節(jié)總結(jié)在開發(fā)中,QObject中常使用的成員函數(shù)和重要宏定義。

1、事件獲取和處理API
/*在此對象上安裝事件篩選器filterObj*/
voidQObject::installEventFilter(QObject*filterObj)

/*這個虛擬函數(shù)接收對象的事件,如果事件e被識別并處理,則返回true*/
boolQObject::event(QEvent*e)
2、對象的線程關(guān)聯(lián)API
/*返回對象所在的線程。*/
QThread*QObject::thread()const

/*更改對象及其子對象的線程關(guān)聯(lián)性。如果一個對象有父對象,則不能移動該對象到另一個線程中*/
voidQObject::moveToThread(QThread*targetThread)

3、獲取子對象API
/*返回該對象具有給定名稱的所有可轉(zhuǎn)換為類型T的子對象,如果沒有此類對象,則返回一個空列表*/
QListfindChildren(constQString&name=QString(),Qt::FindChildOptionsoptions=Qt::FindChildrenRecursively)const

/*返回子對象列表*/
constQObjectList&children()const
4、qobject_cast

函數(shù)原型如下:

Tqobject_cast(QObject*object)
Tqobject_cast(constQObject*object)

如果對象類型為T(或子類),則將給定的對象轉(zhuǎn)換為類型T;否則返回nullptr。如果對象是nullptr,那么它也將返回nullptr。

注意:類T必須繼承(直接或間接)QObject并使用Q_OBJECT宏聲明。

qobject_cast()函數(shù)的行為類似于標(biāo)準(zhǔn)c++ dynamic_cast(),它的優(yōu)點(diǎn)是不需要RTTI(Run-Time Type Identification-運(yùn)行時類型識別)支持,并且可以跨動態(tài)庫邊界工作。

5、事件處理相關(guān)函數(shù)
//此虛函數(shù)用于接收對象的事件,如果事件e被識別和處理,則返回true。
virtualboolevent(QEvent*e)

//如果此對象已作為被監(jiān)視對象的事件過濾器安裝,則過濾事件。
virtualbooleventFilter(QObject*watched,QEvent*event)

//從該對象中移除事件篩選器對象obj。
voidremoveEventFilter(QObject*obj)

//在對象上安裝事件篩選器filterObj
voidinstallEventFilter(QObject*filterObj)
6、定時器相關(guān)函數(shù)
//啟動計時器并返回計時器標(biāo)識符
intstartTimer(intinterval,Qt::TimerTypetimerType=Qt::CoarseTimer)

//啟動計時器并返回計時器標(biāo)識符
intstartTimer(std::millisecondstime,Qt::TimerTypetimerType=Qt::CoarseTimer)

//使用定時器標(biāo)識符id終止計時器
voidkillTimer(intid)
7、重要宏定義
  • Q_DISABLE_COPY(Class)

    禁止對給定類使用復(fù)制構(gòu)造函數(shù)和賦值運(yùn)算符。

  • Q_DISABLE_COPY_MOVE(Class)

該宏用于禁用給定類的復(fù)制構(gòu)造函數(shù)、賦值運(yùn)算符、移動構(gòu)造函數(shù)和移動賦值運(yùn)算符,將Q_DISABLE_COPYQ_DISABLE_MOVE組合在一起。

  • Q_DISABLE_MOVE(Class 5.13)

禁止對給定類使用移動構(gòu)造函數(shù)和移動賦值操作符。

  • Q_EMIT

當(dāng)希望使用第三方信號/槽函數(shù)機(jī)制來使用Qt信號和槽函數(shù)時,可以使用此宏替代emit關(guān)鍵字來發(fā)出信號。

  • Q_ENUM(...)

這個宏用于向元對象系統(tǒng)注冊一個枚舉類型。該宏必須放在enum聲明之后,且放在具有Q_OBJECTQ_GADGET宏的類中。對于命名空間,應(yīng)該使用Q_ENUM_NS()。例如:

classMyClass:publicQObject
{
Q_OBJECT

public:
MyClass(QObject*parent=nullptr);
~MyClass();

enumPriority{High,Low,VeryHigh,VeryLow};
Q_ENUM(Priority)
voidsetPriority(Prioritypriority);
Prioritypriority()const;
};
  • Q_ENUM_NS(...)

這個宏向元對象系統(tǒng)注冊一個枚舉類型。它必須放在enum聲明之后,,且具有Q_NAMESPACE宏的名稱空間中。與Q_ENUM相同,但在命名空間中。

  • Q_FLAG(...)

這個宏向元對象系統(tǒng)中注冊一個單標(biāo)記類型。它通常用于類定義中,以聲明給定enum的值可以用作標(biāo)志,并使用按位或運(yùn)算符進(jìn)行組合。對于命名空間,應(yīng)該使用Q_FLAG_NS()。例如:

classQLibrary:publicQObject
{
Q_OBJECT

public:
...

enumLoadHint{
ResolveAllSymbolsHint=0x01,
ExportExternalSymbolsHint=0x02,
LoadArchiveMemberHint=0x04
};
Q_DECLARE_FLAGS(LoadHints,LoadHint)
Q_FLAG(LoadHint)
...
}
  • Q_INTERFACES(...)

這個宏告訴Qt這個類實(shí)現(xiàn)了哪些接口。在宏定義在實(shí)現(xiàn)插件的時候使用。例如:

classBasicToolsPlugin:publicQObject,
publicBrushInterface,
publicShapeInterface,
publicFilterInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID"org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface"FILE"basictools.json")
Q_INTERFACES(BrushInterfaceShapeInterfaceFilterInterface)

public:
...
};
  • Q_NAMESPACE

Q_NAMESPACE宏用于將QMetaObject功能添加到名稱空間。Q_NAMESPACE可以有Q_CLASSINFOQ_ENUM_NS、Q_FLAG_NS,但不能有Q_ENUM、Q_FLAG、Q_PROPERTYQ_INVOKABLE、信號或槽函數(shù)。

  • Q_NAMESPACE_EXPORT(EXPORT_MACRO)

該宏的工作原理Q_NAMESPACE宏完全相同。但是,在名稱空間中定義的外部staticMetaObject變量是用提供的EXPORT_MACRO限定符聲明的。如果需要從動態(tài)庫導(dǎo)出對象,該宏定義非常有用。

  • Q_OBJECT

Q_OBJECT宏必須出現(xiàn)在類定義的私有部分中,該類定義聲明自己的信號和槽函數(shù),或者使用Qt元對象系統(tǒng)提供的其他支持。

  • Q_PROPERTY(...)

此宏用于在繼承QObject的類中聲明屬性。屬性的行為類似于類數(shù)據(jù)成員,但它們具有可通過元對象系統(tǒng)訪問的其他特性。如下代碼:

Q_PROPERTY(typename
(READgetFunction[WRITEsetFunction]|
MEMBERmemberName[(READgetFunction|WRITEsetFunction)])
[RESETresetFunction]
[NOTIFYnotifySignal]
[REVISIONint]
[DESIGNABLEbool]
[SCRIPTABLEbool]
[STOREDbool]
[USERbool]
[CONSTANT]
[FINAL])
  • Q_SIGNAL

這是一個額外的宏,允許我們將單個函數(shù)標(biāo)記為信號。當(dāng)使用不支持信號或Q_SIGNALS組的第三方源代碼解析器時,使用這個宏。

  • Q_SLOT

這是一個額外的宏,它允許將單個函數(shù)標(biāo)記為槽函數(shù)。當(dāng)使用不支持槽函數(shù)或Q_SLOT組的第三方源代碼解析器時,使用這個宏。

三、信號和槽的連接機(jī)制注意事項(xiàng)

1、【自動連接(默認(rèn))】如果信號是在接收對象具有關(guān)聯(lián)的線程中發(fā)出的,那么行為與直接連接相同。否則,行為與隊列連接相同。

2、【直接連接】當(dāng)信號發(fā)出時,槽函數(shù)被立即調(diào)用。槽函數(shù)在發(fā)射器的線程中執(zhí)行,而發(fā)射器的線程不一定是接收器的線程。

3、【隊列連接】當(dāng)控制返回到接收方線程的事件循環(huán)時調(diào)用槽,槽函數(shù)在接收方的線程中執(zhí)行。

4、【阻塞排隊連接】槽被調(diào)用為排隊連接,除非當(dāng)前線程阻塞直到槽函數(shù)返回。

注意:使用該阻塞排隊連接類型連接同一線程中的對象將導(dǎo)致死鎖。

5、【唯一連接】與自動連接相同,但只在不復(fù)制現(xiàn)有連接的情況下才建立連接。也就是說,如果相同的信號已經(jīng)為相同的對象連接到相同的槽,那么就不創(chuàng)建連接,并且connect()返回false。

連接類型可以通過向connect()傳遞一個附加參數(shù)來指定。注意,如果事件循環(huán)運(yùn)行在接收方的線程中,當(dāng)發(fā)送方和接收方位于不同線程中時使用直接連接是不安全的,這與調(diào)用位于另一個線程中的對象上的函數(shù)是不安全的原因相同。

QObject::connect()本身是線程安全的。

對于隊列連接,傳遞的參數(shù)必須是Qt元對象系統(tǒng)已知的類型,因?yàn)镼t需要復(fù)制參數(shù),以便存儲參數(shù);如果參數(shù)類型不是Qt元對象系統(tǒng)已知的,使用隊列連接,將獲得錯誤提示信息,這時候則需要在創(chuàng)建連接之前,調(diào)用qRegisterMetaType()向元對象系統(tǒng)注冊該數(shù)據(jù)類型。

四、線程關(guān)聯(lián)性

在Qt中,QObject實(shí)例具有線程相關(guān)性,或者可以理解成QObject存在于某個線程中。當(dāng)QObject接收到排隊的信號或發(fā)布的事件時,槽函數(shù)或事件處理程序?qū)⒃谠搶ο笏诘木€程中運(yùn)行,這一點(diǎn)很重要。

注意:如果一個QObject沒有線程關(guān)聯(lián)(也就是說,如果thread()返回0),或者如果它存在于一個沒有運(yùn)行事件循環(huán)的線程中,那么它就不能接收排隊的信號或發(fā)布的事件。

默認(rèn)情況下,QObject實(shí)例存在于創(chuàng)建它的線程中,在實(shí)際開發(fā)中可使用thread()查詢對象的線程關(guān)聯(lián),并使用moveToThread()更改對象的線程關(guān)聯(lián)。

注意:所有QObject必須與它們的父對象生活在同一個線程中。除此之外,還需要知道:

(1)如果涉及的兩個QObject位于不同的線程中,setParent()將失敗。

(2)當(dāng)一個QObject被移動到另一個線程時,它的所有子線程也會被自動移動。

(3)如果QObject有一個父對象,moveToThread()將失敗。

(4)如果QObject是在QThread::run()中創(chuàng)建的,它們不能成為QThread對象的子對象,因?yàn)镼Thread并不存在于調(diào)用QThread::run()的線程中。

QObject的父子關(guān)系必須通過傳遞一個指向子構(gòu)造函數(shù)的指針或調(diào)用setParent()來設(shè)置。如果沒有這個步驟,當(dāng)調(diào)用moveToThread()時,對象的成員變量將保持在舊線程中。

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • API
    API
    +關(guān)注

    關(guān)注

    2

    文章

    1464

    瀏覽量

    61674
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4256

    瀏覽量

    62224
  • Qt
    Qt
    +關(guān)注

    關(guān)注

    1

    文章

    300

    瀏覽量

    37731

原文標(biāo)題:Qt的萬能承載者QObject,了解多少?

文章出處:【微信號:嵌入式小生,微信公眾號:嵌入式小生】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    C語言定義使用技巧

    寫好C語言,漂亮的定義重要,使用定義可以防止出錯,提高可移植性,可讀性,方便性等等。下面列舉一些成熟軟件
    發(fā)表于 07-29 09:35 ?1083次閱讀

    C語言中常用的定義

    寫好C語言,漂亮的定義重要,使用定義可以防止出錯,提高可移植性,可讀性,方便性等等。下面列舉一些成熟軟件
    發(fā)表于 10-18 10:05 ?1617次閱讀

    C語言中定義的應(yīng)用

    在C語言中,定義是一種預(yù)處理指令,用于在代碼中定義和使用常量、函數(shù)或代碼片段的替代。
    發(fā)表于 08-17 15:33 ?662次閱讀

    C編程定義函數(shù)該如何修改?

    那么該如何修改呢?不希望寫成函數(shù)形式的,寫成定義形式的比較好。
    發(fā)表于 12-26 08:51

    c語言中常用的定義有哪些?

    c語言中常用的定義有哪些?
    發(fā)表于 04-28 06:01

    C語言定義使用技巧

    寫好C語言,漂亮的定義重要,使用定義可以防止出錯,提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟件
    發(fā)表于 11-13 12:04 ?36次下載

    內(nèi)聯(lián)函數(shù)定義的區(qū)別介紹

    定義是C語言提供的三種預(yù)處理功能的其中一種,這三種預(yù)處理包括:定義、文件包含、條件編譯。定義
    發(fā)表于 12-15 15:33 ?2314次閱讀
    內(nèi)聯(lián)<b class='flag-5'>函數(shù)</b>和<b class='flag-5'>宏</b><b class='flag-5'>定義</b>的區(qū)別介紹

    定義 “中斷函數(shù)接口”的注意事項(xiàng)

    定義“中斷函數(shù)接口”的注意事項(xiàng)
    的頭像 發(fā)表于 03-07 16:42 ?2432次閱讀

    ARM Linux中一些重要及地址定義

    ARM Linux中一些重要及地址定義
    的頭像 發(fā)表于 06-22 17:02 ?2670次閱讀

    一些成熟軟件中常用的定義

    寫好C語言,漂亮的定義重要,使用定義可以防止出錯,提高可移植性,可讀性,方便 性等等。 下面列舉一些成熟軟件
    的頭像 發(fā)表于 01-18 11:21 ?2309次閱讀

    C語言定義與預(yù)處理、函數(shù)函數(shù)

    目錄前言一、C語言預(yù)處理二、定義三、函數(shù)四、函數(shù)庫五、自己制作靜態(tài)鏈接庫(ubuntu 環(huán)境下,即使用Linux系統(tǒng)平臺上的gcc)六、自己制作動態(tài)鏈接庫(ubuntu 環(huán)境下,即使
    發(fā)表于 12-07 21:06 ?2次下載
    C語言<b class='flag-5'>宏</b><b class='flag-5'>定義</b>與預(yù)處理、<b class='flag-5'>函數(shù)</b>和<b class='flag-5'>函數(shù)</b>庫

    類的申明和成員函數(shù)定義分離是什么

    前面我們學(xué)習(xí)了如何定義類,以及如何使用類的成員,在前面我們把成員函數(shù)定義在了類的內(nèi)部,接下來我們學(xué)習(xí),如何把類的
    的頭像 發(fā)表于 02-27 15:33 ?833次閱讀

    C語言函數(shù)封裝技巧分享

    函數(shù),即包含多條語句的定義,其通常為某一被頻繁調(diào)用的功能的語句封裝,且不想通過函數(shù)方式封裝來降低額外的彈棧壓棧開銷。
    的頭像 發(fā)表于 09-14 09:31 ?560次閱讀

    列舉一些C語言中常用的定義

    寫好C語言,使用定義可以防止出錯,提高可移植性、可讀性等。下文列舉一些成熟軟件中常用的定義
    發(fā)表于 10-07 10:54 ?482次閱讀
    列舉一些C語言<b class='flag-5'>中常</b>用的<b class='flag-5'>宏</b><b class='flag-5'>定義</b>

    C語言中函數(shù)定義和用法

    函數(shù)是一種特殊的函數(shù),與普通函數(shù)不同的是,它可以擁有多條語句和局部變量,從而實(shí)現(xiàn)更復(fù)雜的功
    發(fā)表于 10-11 11:32 ?3067次閱讀
    C語言中<b class='flag-5'>宏</b><b class='flag-5'>函數(shù)</b>的<b class='flag-5'>定義</b>和用法