官方解釋
我們在Qt源碼中可以看到一個QObject的子類經常會用到一些Q_開頭的宏,例如QMainWindow類開始部分代碼是這樣的:
Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize)
Q_PROPERTY(Qt::ToolButtonStyle toolButtonStyle READ toolButtonStyle WRITE setToolButtonStyle)
......
public:
enum DockOption {
AnimatedDocks = 0x01,
AllowNestedDocks = 0x02,
AllowTabbedDocks = 0x04,
ForceTabbedDocks = 0x08, // implies AllowTabbedDocks, !AllowNestedDocks
VerticalTabs = 0x10, // implies AllowTabbedDocks
GroupedDragging = 0x20 // implies AllowTabbedDocks
};
Q_ENUM(DockOption)
Q_DECLARE_FLAGS(DockOptions, DockOption)
Q_FLAG(DockOptions)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
這幾個宏也不是標准C++的內容,它們屬於Qt的屬性系統,是元對象系統的一部分。使用屬性系統的類必須是QObject的子類,還得包含宏Q_OBJECT。
在標准C++中,為了保證封裝性,我們經常聲明一個私有變量,然后聲明兩個公有函數,即set函數和get函數。在Qt中我們可以使用宏Q_PROPERTY來實現這些,還包括信號的發射,后者實際是在set函數中實現的。
Q_PROPERTY(type name
READ getFunction
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal] )
Q_PROPERTY(type name
MEMBER memberName
[READ getFunction]
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal] )
1
2
3
4
5
6
7
8
9
10
11
12
這是Q_PROPERTY的兩種簡單而常用的形式。
type 是指屬性的類型,可以是 C++ 標准類型、類名、結構體、枚舉等
name 屬性的名字,僅僅是一個用於標識屬性的名字,不是實際存在的成員變量
READ 標出該屬性的讀函數 getFunction,Qt 屬性的讀函數通常省略 get 三個字母。
WRITE 標出該屬性的寫函數 setFunction,中括號表示可選,寫函數不是必須的。
RESET 標出該屬性的重置函數
resetFunction,重置函數將屬性設為某個默認值,中括號表示可選,重置函數不是必須的。
NOTIFY 標出該屬性變化時發出的通知信號 notifySignal,中括號表示可選,這個信號不是必須的。
在明確標出屬性使用的成員變量的情況下,屬性的讀寫函數可以省略不寫,Qt 的 moc 工具會自動為成員變量生成讀寫代碼。比如:
READ, WRITE以及RESET可以被繼承,也可以是虛函數。property的類型可以是QVariant支持的任何類型,也可以是用戶定義的類型,這就是Q_ENUM()的作用了。
枚舉類型必須用Q_ENUM()宏注冊,這也是元對象系統的一部分,然后就可以使用QObject::setProperty(); 我們必須為READ和WRITE提供自己的聲明。
結合以上幾條,我們這樣寫一個類:
class MainWindow : public QMainWindow
{
Q_OBJECT
Q_PROPERTY(int value MEMBER m_value NOTIFY valueChanged);
Q_PROPERTY(Priority prioity MEMBER m_priority NOTIFY priChanged);
public:
MainWindow(QWidget* parent= nullptr);
~MainWindow();
enum Priority{Low,High, VeryHigh};
Q_ENUM(Priority);
signals:
void valueChanged();
void priChanged();
private:
Ui::MainWindow* ui;
int m_value;
Priority m_priority;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
這樣就可以在類外調用相關函數了:
m.setProperty("value",15);
m.setProperty("prioity",MainWindow::VeryHigh);
qDebug()<<"value:"<<m.property("value").toInt();
qDebug()<<"prioity value:"<<m.property("prioity").toInt();
qDebug()<<m.dynamicPropertyNames();
1
2
3
4
5
6
還有一個宏Q_FLAG(), 它與Q_ENUM()類似, 也是注冊枚舉類型, 但可以使用|操作。一個I/O類可能有枚舉值Read和Write ,那么QObject::setProperty()就可以接受Read | Write。記得必須用Q_DECLARE_FLAGS完成注冊
還有一個宏Q_CLASSINFO(),在類的聲明里添加類附加信息,比如:
Q_CLASSINFO("Version", "1.0.0")
1
附加信息也是成對的“名稱-值”,不過注意 名稱和值 都是普通字符串。如果希望在運行時查詢類的附加信息,可以先用 QObject::metaObject() 獲取當前對象包含的元對象數據,然后使用 QMetaObject::classInfo 函數查詢某個序號的附加信息:
//類內聲明
Q_CLASSINFO("Version", "1.0.0")
Q_CLASSINFO("Author", "Winland")
//類外使用
//獲取類的附加信息
const QMetaObject *pMO = w.metaObject();
//附加信息個數
int nInfoCount = pMO->classInfoCount();
//打印所有的附加信息
for(int i=0; i<nInfoCount; i++)
{
QMetaClassInfo info = pMO->classInfo(i);
qDebug()<<info.name()<<"\t"<<info.value();
}
---------------------
作者:SilentAssassin
來源:CSDN
原文:https://blog.csdn.net/yao5hed/article/details/81142358?utm_source=copy
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!