QT內省機制、自定義Model、數據庫

QT內省機制、自定義Model、數據庫


本文將介紹自定義Model過程中數據庫數據源的獲取方法,我使用過以下三種方式獲取數據庫數據源:

  • 創建 存儲對應數據庫所有字段的 結構體,將結構體置於容器中返回,然後根據索引值(QModelIndex)取出最終的字段值;

  • 創建 存儲對應數據庫所有字段的 類,將類對象置於容器中返回,然後利用內省機制獲取對象相應字段(屬性)值。

  • 不用自己造輪子,直接使用QVariantList類,將QVariantList 對象置於容器中,如QVector<QVariantList >,然後根據索引值(QModelIndex)取出最終的字段值;

本文重點介紹第二種,即利用QT的內省機制來獲取數據。

 

1.自定義Model過程(通過內省功能獲得字段值,也就是第二種方法)

本文中自定義Model繼承於QAbstractTableModel ,重點描述setData(..)函數與data(...)函數的重載過程。

 

 

首先需要介紹 Parameter類,該類用於存儲查詢數據庫中某表所得的字段值。

複製代碼

 1 //Parameter.h 2 //加粗單詞爲成員變量 3 //假設數據庫中某表有三個字段Index,Name,Describe 4  5 class Parameter : public QObject 6 { 7     Q_OBJECT 8 public: 9     explicit Parameter( QObject *parent = 0);10 11     Q_INVOKABLE QVariant getIndex() const { return index;} //用Q_INVOKABLE聲明後才能被元對象(QMetaObject)調用12     Q_INVOKABLE void setIndex(const QVariant &value) { index = value.toInt(); }13 14     Q_INVOKABLE QVariant getName() const { return name; }15     Q_INVOKABLE void setName(const QVariant &value) { name = value.toString(); }16 17     Q_INVOKABLE QVariant getDecribe() const { return describe; }18     Q_INVOKABLE QVariant setDescribe(const QVariant &value) { describe = value; }19 20     QMap<int, int> getMethodGETIndexs()const;//獲得“取值器”函數(即getXX函數)  的索引值列表,這些函數都被Q_INVOKABLE聲明過21     QMap<int, int> getMethodSETIndexs() const;//獲得“設置器”函數(即setXX函數) 的索引值列表,這些函數都被Q_INVOKABLE聲明過22 23 private:24     void setMethodGETIndexs(); //設置“取值器”函數(即getXX函數) 的索引值列表,這些函數都被Q_INVOKABLE聲明過25     void setMethodSETIndexs(); //設置“設置器”函數(即setXX函數) 的索引值列表,這些函數都被Q_INVOKABLE聲明過26 27     static int getNewIndex();28 29     int index;30     QString name;31     QString describe;32 33     QMap<int,int> methodGETIndexs;34     QMap<int,int> methodSETIndexs;35 };

複製代碼

複製代碼

 1 //Parameter.cpp 2  3 Parameter::Parameter(QObject *parent) : 4   QObject(parent), 5   index(getNewIndex()), 6   name("Unnamed"), 7   describe("") 8 { 9    setMethodGETIndexs();10    setMethodSETIndexs();   
11 }12 13 void Parameter::setMethodGETIndex()14 {15   int index1 = this->metaObject()->indexOfMethod("getIndex()");16   methodGETIndexs.insert(0,index1);17 18   int index2 = this->metaObject()->indexOfMethod("getName()");19   methodGETIndexs.insert(1,index2);20 21   int index3 = this->metaObject()->indexOfMethod("getDecribe()");22   methodGETIndexs.insert(2,index3);23 24 }25 26 void Parameter::setMethodSETIndexs()27 {28   int index1 = this->metaObject()->indexOfMethod("setIndex(QVariant)");29   methodSETIndexs.insert(0,index1);30 31   int index2 = this->metaObject()->indexOfMethod("setName(QVariant)");32   methodSETIndexs.insert(1,index2);33 34   int index3 = this->metaObject()->indexOfMethod("setDescribe(QVariant)");35   methodSETIndexs.insert(2,index3);36 }37 38 QMap<int, int> Parameter::getMethodSETIndexs() const39 {40   return methodSETIndexs;41 }42 43 QMap<int, int> Parameter::getMethodGETIndexs() const44 {45   return methodGETIndexs;46 }47 48 int Parameter::getNewIndex()49 {50      //查詢數據庫51      //返回最新的Index字段52 }

複製代碼

Parameter類聲明瞭對應數據庫表中字段(field)的成員變量,並分別爲這些成員變量編寫了setxx()函數和getxx()函數,並對這些函數進行Q_INVOKABLE聲明

然後,在setMethodGETIndexs()函數 與 setMethodSETIndexs()函數中,使用QMetaObject::indexOfMethod(...)函數獲取每個函數在QMetaObject對象中的索引值,將該按順序索引值存入到容器中,其插入順序與TableModel中的字段順序一致。

最後,在TableModel中調用Parameter類的getMethodSETIndexs()函數與getMethodGETIndexs()函數獲得索引值列表。

 

複製代碼

 1 //TableModel.h 2 class TableModel : public QAbstractTableModel 3 { 4     Q_OBJECT 5 public: 6     explicit TableModel(QObject *parent = 0); 7     int rowCount(const QModelIndex &parent = QModelIndex()) const;// 8     int columnCount(const QModelIndex &parent = QModelIndex()) const; 9     QVariant data(const QModelIndex &index, int role) const;10     bool setData(const QModelIndex &index, const QVariant &value, int role);11 private:12     static  QList<Parameter*> getTableParameters(); //該函數用於初始化dataParameters13 14     QVariant specificIndexValue(const QModelIndex &index) const;15     int getMethodGETIndex(const QModelIndex &index) const;16     QMetaMethod getMetaMethod(const QModelIndex &index,int methodIndex) const;17     bool setSpecificData(const QModelIndex &index, const QVariant &value);18     int getMethodSETIndex(const QModelIndex &index);19 20     QList<Parameter*> dataParameters; //存儲從數據庫表中查詢所得的值,每個Parameter對象代表一條記錄

複製代碼

 

複製代碼

//tablemodel.cpp

TableModel::TableModel(QObject * TableModel::QList<Parameter*> TableModel::rowCount( QModelIndex &parent = TableModel::columnCount( QModelIndex &parent)  QModelIndex &index,  role) (! QModelIndex &index,  role) (Qt::AlignHCenter | QModelIndex &index)  methodIndex == TableModel::getMethodGETIndex( QModelIndex &index)  methodIndex = dataParameters.at(index.row())-> QModelIndex &index, methodIndex) = dataParameters.at(index.row())->metaObject()-> TableModel::setData( QModelIndex &index,  QVariant &value, (! (role == Qt::EditRole && TableModel::setSpecificData( QModelIndex & QVariant &( specificIndexValue(index) != methodIndex ==  TableModel::getMethodSETIndex( QModelIndex & methodIndex = dataParameters.at(index.row())->

複製代碼

成員變量 QList<Parameter*> dataParameters中存儲了數據庫表中的字段值,且每個Parameter對象代表一條記錄。

 

我們知道,TableModel數據的顯示與rowCount()、columnCount()、data()函數息息相關,我們重載了這三個函數。

爲了讓model的行和列與dataParameters一一對應:

令rowCount()函數返回dataParameters的條目數(行數目);

令columnCount()返回dataParameters中每條記錄的字段數目(列數目)。

對於Variant data(const QModelIndex &index, int role) const函數,在選定的role下,調用specificIndexValue(const QModelIndex &index)函數,根據索引值獲得行號和列號,先根據行號確定容器中某一個Parameter對象(即某一條記錄),然後再根據列號,獲得該Parameter對象中支持 元對象調用的 函數的索引值(如getMethodGETIndex()函數所示),獲取函數索引值後,如getMetaMethod()所示,可獲得QMetaMethod對象,然後調用invoke()函數,賦予合適的參數值,就等價於調用當前函數索引值對應的那個函數。

這樣做的好處在於,可直接通過行號與列號進行尋址,避免了條件判斷語句,使代碼大大提高了簡潔性與複用性。

setData()函數與data()函數類似,不再詳述。

 

總結:利用內省機制獲得對象的成員函數,並調用之,能夠避免複雜的條件判斷邏輯,能夠提高複用性。但是,在這裏沒有提及的有性能問題,我沒有研究對性能會有什麼影響,當然,簡單的PC軟件是基本看不到影響的,其次,利用Parameter類存儲數據庫表字段值,使Parameter只能用於同一個表,那麼每個返回數據庫字段值的函數也就只能服務於同一個表,這樣也會有很多重複代碼產生。所以接下來,我將進一步改進,放棄利用自定義類而使用QVariantList類來存儲數據庫表的每一條記


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章