學習Qt之屬性系統詳解


一、屬性系統有什麼用?

一般我們說一個類有什麼屬性,指的就是這個類有啥成員變量。比如People類中有個int age的私有成員變量,我們就可以說這個People類有個“年齡”屬性可以更改讀取。

Qt提供的屬性系統,作用就是把類的信息暴露出來成爲通用的、大家都認識的信息。比如用C++語言寫的People類中中有個int age變量,但所如果用QML語言去讀取就會出問題,因爲QML有自己的規則,它不認識C++規則。用Qt的屬性系統就可以解決這個問題,當一個類的成員變量或者成員函數用屬性系統處理一下,它們就從C++內部中暴露出來,而且大家都認得
在這裏插入圖片描述

屬性系統是專門爲元對象系統服務


二、屬性詳解

Qt提供一個Q_PROPERTY()宏可以定義屬性,它也是基於元對象系統實現的。Qt的屬性系統與C++編譯器無關,可以用任何標準的C++編譯器編譯定義了屬性的Qt C++程序。

在QObject的子類中,用宏Q_PROPERTY()定義屬性,其使用格式如下:

Q_PROPERTY(type name (READ getFunction [WRITE setFunction] | MEMBER memberName  [(READ getFunction | WRITE setFunction)])
		[RESET resetFunction]
		[NOTIFY int]
		[REVISION int]
		[DESIGNABLE bool]
		[SCRIPTABLE bool]
		[STORED bool]
		[USER bool]
		[CONSTANT]
		[FINAL])

注意

getFunction的返回值類型必須爲type;
setFunction的返回值必須爲空,而且必須帶一個參數
例如:type getFunction();void setFunction(type n);
指定了MEMBER之後就能再指定READ和WRITE

Q_PROPERTY()宏定義一個返回值類型爲type,名稱爲name的屬性,用READ、WRITE關鍵字定義屬性的讀取、寫入函數,還有其他的一些關鍵字定義屬性的一些操作特性。屬性的類型可以是QVarient支持的任何類型,也可以用戶自定義類型。

Q_PROPERTY()宏定義屬性的一些關鍵字的意義如下:

  • READ:指定一個讀取屬性值的函數,沒有MEMBER關鍵字必須設置READ。
  • WRITE:指定一個設定屬性值的函數,只讀屬性沒有WRITE設置。
  • MEMBER:指定一個成員變量與屬性關聯,成爲可讀科協的屬性,無需再設置READ和WRITE。
  • RESET:可選,用於指定一個設置屬性缺省值的函數。
  • NOTIFY:可選,用於設置一個信號,當屬性值變化時發射此信號。
  • DESIGNABLE:表示屬性是否在Qt Dseigner裏可見,缺省爲true。
  • CONSTANT:表示屬性值是一個常數,對於一個對象示例,READ指定的函數返回值是常數,但是每個實例的返回值可以不一樣。具體CONSTANT關鍵字的屬性不能有WRITE和NOTIFY關鍵字。
  • FINAL:表示所定義的屬性不能被子類重載。

三、屬性定義

1. READ和WRITE

//頭文件
Class Widget : public QObject
{
		Q_PROPERTY(int age READ readAge WRITE setAge)
		Q_OBJECT
public:
		explicit Widget(QWidget *parent = 0);
   		 ~Widget();
   		 
		int my_age;
		
		int readAge();
		void setAge(int n);
}

//源文件
int Widget::readAge()
{
		return my_age;
}
void Widget::setAge(int n)
{
		my_age = n;
}

2. MEMBER

//頭文件
Class Widget : public QObject
{
		Q_PROPERTY(int age MEMBER my_age NOTIFY ageChanged)
		Q_OBJECT
public:
		explicit Widget(QWidget *parent = 0);
   		 ~Widget();

		int my_age;

		int readAge();
		void setAge(int n);
signal:
		void ageChanged();
}

//源文件
int Widget::readAge()
{
		return my_age;
}
void Widget::setAge(int n)
{
		my_age = n;
}

四、屬性使用

如果是用READ、WRITE,直接調用指定的函數即可,例如:

Widget *w = new Widget;
w->setAge(true);

如果是用MEMBER,那麼用QObject的property()setProperty()兩個函數,如:

Widget *w = new Widget;
w->property("age");
w->setProperty("age",18);

兩種方法,使用WRITE效率更高、速度更快,而且在編譯階段就可以進行類型檢查。缺點就是還沒運行前你就得了解這個類使用readAge()這個函數。而採用MEMBER方式時,我們不需要知道這個類有啥函數、有啥變量,只需要知道這個類有一個叫“age”的屬性值就可以。


五、類的附加信息

屬性系統還有一個宏Q_CLASSINFO(),可以爲類的元對象定義“名稱–值”信息,如:

//頭文件
Class Widget : public QObject
{
		Q_CLASSINFO("author","Wang")
		Q_CLASSINFO("version","3.0.1")
		Q_OBJECT
public:
		explicit Widget(QWidget *parent = 0);
   		 ~Widget();
}

//使用
Widget *w = new Widget;
w->metaObject()->classInfo(0).name();
w->metaObject()->classInfo(0).value();

w->metaObject()->classInfo(1).name();
w->metaObject()->classInfo(1).value();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章