1. 程式人生 > 實用技巧 >QT之Qt之Q_PROPERTY巨集理解

QT之Qt之Q_PROPERTY巨集理解

在初學Qt的過程中,時不時地要通過F2快捷鍵來檢視QT類的定義,發現類定義中有許多Q_PROPERTY的東西,比如最常用的QWidget的類定義:

Qt中的Q_PROPERTY巨集在Qt中是很常用的,那麼它有什麼作用呢?

Qt提供了一個絕妙的屬性系統,Q_PROPERTY()是一個巨集,用來在一個類中宣告一個屬性property,由於該巨集是qt特有的,需要用moc進行編譯,故必須繼承於QObject類。

Q_PROPERTY(type name
      READ getFunction
      [WRITE setFunction]
      [RESET resetFunction]

      [NOTIFY notifySignal]
      [DESIGNABLE bool]
      [SCRIPTABLE bool]
      [STORED bool]
      [USER bool]
      [CONSTANT]
      [FINAL])

之前一直在使用VS開發C++程式,接觸過開發Ocx控制元件會有控制元件屬性設定,Qt這裡的屬性系統可以和之前的知識聯絡起來,Qt的屬性功能使得我們可以選擇訪問資料成員的方式,屬性就像是類的資料成員,但是在元物件系統中,它的其他特性是到處可見的(相比較於類成員的一般情況下私有化)。

我們使用這個巨集的時候,注意兩個問題:

1)型別,屬性名和READ(讀)方法是必須的。也就是前三個引數可必須有的。型別可以是QVariant支援的任一型別,又或者是我們自定義的型別,其他是可選的。下面的title屬性定義可以這麼來說明:定義一個屬性title,型別是QString,讀title的方法是title()函式,寫title的方法是setTitle,這裡USER表示是否使用者自定義型別,這裡應該設定為false。

2)屬性宣告完了以後,我們還需要進行讀寫函式的宣告和定義

為什麼要使用它呢?在哪裡使用它呢?

答:Qt中類的屬性是給指令碼和元物件系統用的,比如QtScript,QML,或者QObject::property/setProperty……,主要就是用來進行屬性封裝,在具體的指令碼,庫,qml開發中必須使用。

最常見的是在QML中訪問C++,通過C++類暴露屬性來使用,接上面例項如下:

1、新建Qt Quick工程:qt PROPERTY

2、新建C++類TestProperty,公有繼承於QObject

3、為TestProperty類設定上述屬性title

Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged);

4、屬性讀寫函式宣告與實現

TestProperty.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

#ifndefTESTPROPERTY_H
#defineTESTPROPERTY_H

#include<QObject>

classTestProperty:publicQObject
{
Q_OBJECT
public:
explicitTestProperty(QObject*parent=nullptr);
Q_PROPERTY(QStringtitleREADtitleWRITEsetTitleNOTIFYtitleChanged);

QStringtitle();
voidsetTitle(QStringstrTitle);


signals:
voidtitleChanged();

publicslots:

private:
QStringm_title;

};

#endif//TESTPROPERTY_H

TestProperty.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

#include"TestProperty.h"

TestProperty::TestProperty(QObject*parent):QObject(parent)
{

}

QStringTestProperty::title()
{
returnm_title;
}

voidTestProperty::setTitle(QStringstrTitle)
{
m_title=strTitle;
emittitleChanged();
}

5、在main函式中註冊這個類,匯出到qml中

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#include<QGuiApplication>
#include<QQmlApplicationEngine>
#include<qglobal.h>
#include"TestProperty.h"

intmain(intargc,char*argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

QGuiApplicationapp(argc,argv);

qmlRegisterType<TestProperty>("TestProperty",1,0,"TestProperty");
QQmlApplicationEngineengine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if(engine.rootObjects().isEmpty())
return-1;

returnapp.exec();
}

6、在qml中呼叫title屬性

main.qml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

importQtQuick2.9
importQtQuick.Window2.2
importTestProperty1.0

Window{
visible:true
width:640
height:480
title:qsTr("HelloQt")

TestProperty{
id:testProperty
title:qsTr("HelloWorld")
}

Component.onCompleted:{
title=testProperty.title;
}
}

執行後: