在初學Qt的過程中,時不時地要通過F2快捷鍵來查看QT類的定義,發現類定義中有許多Q_PROPERTY的東西,比如最常用的QWidget的類定義:
Qt中的Q_PROPERTY宏在Qt中是很常用的,那么它有什么作用呢?
Qt提供了一個絕妙的屬性系統,Q_PROPERTY()是一個宏,用來在一個類中聲明一個屬性property,由於該宏是qt特有的,需要用moc進行編譯,故必須繼承於QObject類。
如何理解“屬性系統”這個概念?
一般我們說一個類有什么屬性,指的就是這個類有啥成員變量。比如 People 類中有個 int age 的私有成員變量,我們就可以說這個 People 類有個“年齡”屬性可以更改讀取。
Qt 提供的這個屬性系統,作用就是把類的信息暴露出來成為通用的大家都認識的信息。比如用 C++ 語言寫的People 類中有個 int age 變量,但是如果用 QML 語言去讀取就會出問題,因為 QML 有自己的規則,它不認識 C++ 啊。怎么辦呢?用 Qt 的屬性系統就可以解決這個問題。屬性系統可以這樣理解:當一個類的成員變量或者成員函數用屬性系統處理一下,它們就從 C++ 內部中暴露出來,而且大家都認得。
屬性系統是專門為元對象系統服務的。
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、屬性讀寫函數聲明與實現
class TestProperty : public QObject
{
Q_OBJECT
public:
explicit TestProperty(QObject *parent = nullptr);
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged);
QString title();
void setTitle(QString strTitle);
signals:
void titleChanged();
public slots:
private:
QString m_title;
};
QString TestProperty::title()
{
return m_title;
}
void TestProperty::setTitle(QString strTitle)
{
m_title = strTitle;
emit titleChanged();
}
5、在main函數中注冊這個類,導出到qml中
#include <qglobal.h>
#include "TestProperty.h"
qmlRegisterType<TestProperty>("TestProperty", 1, 0, "TestProperty");
6、在qml中調用title屬性
import QtQuick 2.9
import QtQuick.Window 2.2
import TestProperty 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello Qt")
TestProperty{
id: testProperty
title: qsTr("Hello World")
}
Component.onCompleted: {
title = testProperty.title;
}
}
運行后: