使用C++實現QML的TreeView Model (一)_PHP教程

來源:互聯網
上載者:User

使用C++實現QML的TreeView Model (一)


QML中的資料訪問組件如ListView、TableView、GridView通常使用ListModel做為資料提供者,這種應用有相當大局限性,如無法訪問本地檔案系統、無法串連到傳統的SQL資料庫,所以通常在使用中都是通過C++實現資料訪問,通過QML進行資料展示和編輯,常用的資料模型組件有QAbstractItemModel、QAbstractTableModel、QSQLTableModel等。所有的進階Model組件都繼承自QAbstractItemModel,只要瞭解QAbstractItemModel的介面函數和運作機理,就可以瞭解QT的Model/View機制實現方式。
QAbstractItemModel是一個抽象類別,要執行個體化QAbstractItemModel必須繼承並至少實現以下5個方法:

int rowCount(const QModelIndex &parent=QModelIndex()) const;
int columnCount(const QModelIndex &parent=QModelIndex()) const;
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const;
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
QModelIndex parent(const QModelIndex &child) const;
與 QWidget組件不同的是,在QML的資料模型中,並不通過列(Column)進行資料訪問,而是通過Role進行資料訪問,例如:

 
  1. TableView{
  2. id:tableView1
  3. anchors.fill: parent
  4. TableViewColumn{
  5. width:50
  6. title:""
  7. role:"tagging"
  8. }

  9. TableViewColumn{
  10. width:80
  11. title:"操作"
  12. role:"name"
  13. }
  14. }
TableViewColumn是TableView的列定義,TableViewColumn通過role屬性定義來向model擷取資料,TableView會通過調用model的roleNames()方法來擷取model可用的role。所以,除了必須要實現的5個虛函數外,還必須重新實現roleNames()來告訴View有哪些role是可用的,roleNames()的原型如下:


 
  1. QHash roleNames() const;



以下是一個完整的Model類定義:

 
  1. classSqlMenuEntry:public QAbstractItemModel,public QQmlParserStatus
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit SqlMenuEntry(QObject *parent=0);
  6. ~SqlMenuEntry();
  7. enum MenuEntryRoles{idRole=Qt::UserRole+1,nameRole,defaultEntryRole,customEntryRole,iconRole,iconHoverRole};
  8. int rowCount(const QModelIndex &parent=QModelIndex()) const;
  9. int columnCount(const QModelIndex &parent=QModelIndex()) const;
  10. QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const;
  11. QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
  12. QModelIndex parent(const QModelIndex &child) const;
  13. QHashroleNames() const;
  14. private:
  15. QHash mRoleNames;
  16. QList> mRecords; //真正的資料儲存在這裡,QList只能儲存二維資料沒辦法儲存樹狀節點,這裡僅僅是例子
  17. };

roleNames()的實現相當簡單:

 
  1. QHash SqlMenuEntry::roleNames() const
  2. {
  3. return mRoleNames;
  4. }
mRoleNames可以在類建構函式中進行初始化:

 
  1. SqlMenuEntry::SqlMenuEntry(QObject *parent)
  2. :QAbstractItemModel(parent)
  3. {
  4. mRoleNames[nameRole] = "name";
  5. mRoleNames[idRole] = "menuid";
  6. mRoleNames[iconRole] = "icon";
  7. mRoleNames[defaultEntryRole] = "default";
  8. mRoleNames[iconHoverRole] = "iconHover";
  9. }
在QML中就可以通過"name"、"menuid"、"icon"對資料進行訪問:

 
  1. ListView{
  2. model:MenuEntryModel{ }
  3. delegate:Item{
  4. Column{
  5. Text{text:name}
  6. Text{text:icon}
  7. }
  8. }
  9. }
如果僅為二維表提供資料,那麼根據以上幾個介面函數的名稱就可以簡單的實現資料供給View視圖,其中:


 
  1. int SqlMenuEntry::rowCount(const QModelIndex &parent) const
  2. {
  3. return mRecords.size();

  4. }
  5. int SqlMenuEntry::columnCount(const QModelIndex &parent) const
  6. {
  7. return 1; //QML不使用列擷取資料,預設返回一列,不返回1例的話,View控制項會認為表是空表,不擷取資料
  8. }
  9. QModelIndex SqlMenuEntry::index(int row, int column, const QModelIndex &parent) const
  10. {
  11. if((row >= 0)&&(row < mRecords.size()))
  12. {
  13. return createIndex(row,column);
  14. }
  15. return QModelIndex(); //返回一個無效的空索引
  16. }
  17. QModelIndex SqlMenuEntry::parent(const QModelIndex &child) const
  18. {
  19. return QModelIndex(); //二維表中的行沒有parent節點
  20. }
  21. QVariant SqlMenuEntry::data(const QModelIndex &index, int role) const
  22. {
  23. if(index.isValid)
  24. {
  25. return mRecords[index.row()][role];
  26. }
  27. }



mRecords中的資料可以按需求產生,如通過QSqlQuery組件從資料庫伺服器擷取,擷取添加資料:

 
  1. QHash row;
  2. row[nameRole] = "name1";
  3. row[iconRole] = "icon1";
  4. mRecords.append(row);
實現後的model類可以通過

 
  1. qmlRegisterType("com.limutech.tv",1,0,"MenuEntryModel");
進行註冊,註冊後的類可以在QML產生執行個體:

 
  1. import com.limutech.tv 1.0
  2. MenuEntryModel{
  3. id:menuEntryModel
  4. }
  5. ListView{
  6. model:menuEntryModel
  7. ...
  8. }
View組件擷取資料的流程大概如下:
1、View調用rowCount(constQModelIndex &parent)並傳遞一個空的parent擷取根節點的行數;
2、View調用columnCount(const QModelIndex &parent)並傳遞一個空的parent擷取根節點的列數;
3、View對各行列枚舉調用index(int row, int column, const QModelIndex &parent)交傳行號、列號和空的parent擷取根節點QModelIndex;
4、繼續以返回的modelIndex為parent擷取每行的rowCount和columnCount,如果大於0則該節點還有子節點;
5、調用roleNames返回可用的role列表
6、以返回的modelIndex和role為參數,調用data擷取資料並使用相應的delegate進行顯示
所以要顯示一個樹狀列表,需要對二維表模型進行完善,處理parent不為空白的情況,同時,模型應該可以儲存樹狀資料,在下一節我將繼續分享層次模型的實現方式和涉及資料修改的一些實現。








http://www.bkjia.com/PHPjc/1120299.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1120299.htmlTechArticle使用C++實現QML的TreeView Model (一) QML中的資料訪問組件如ListView、TableView、GridView通常使用ListModel做為資料提供者,這種應用有相當大局限...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.