全球彩票平台_全球彩票注册平台|官网下载地址

热门关键词: 全球彩票平台,全球彩票注册平台,全球彩官网下载地址

自家从没会晤过

使用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进行数据访问,例如:

TableView{
 id:tableView1
anchors.fill: parent
TableViewColumn{
width:50
title:""
role:"tagging" }

TableViewColumn{
width:80
title:"操作"
role:"name" } } 

TableViewColumn是TableView的列定义,TableViewColumn通过role属性定义来向model获取数据,TableView会通过调用model的roleNames()方法来获取model可用的role。所以,除了必须要实现的5个虚函数外,还必须重新实现roleNames()来告诉View有哪些role是可用的,roleNames()的原型如下:

QHash roleNames() const; 

以下是一个完整的Model类定义:

classSqlMenuEntry:public QAbstractItemModel,public QQmlParserStatus
 {
Q_OBJECT
public:
explicit SqlMenuEntry(QObject *parent=0);
~SqlMenuEntry();
enum MenuEntryRoles{idRole=Qt::UserRole 1,nameRole,defaultEntryRole,customEntryRole,iconRole,iconHoverRole};
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;
QHashroleNames() const;
private:
QHash mRoleNames;
 QList> mRecords; //真正的数据保存在这里,QList只能保存二维数据没办法保存树状节点,这里仅仅是例子
};

roleNames()的实现相当简单:

QHash SqlMenuEntry::roleNames() const
 {
return mRoleNames;
} 

mRoleNames可以在类构造函数中进行初始化:

SqlMenuEntry::SqlMenuEntry(QObject *parent)
 :QAbstractItemModel(parent)
{
mRoleNames[nameRole] = "name";
mRoleNames[idRole] = "menuid";
mRoleNames[iconRole] = "icon";
mRoleNames[defaultEntryRole] = "default";
mRoleNames[iconHoverRole] = "iconHover";
} 

在QML中就可以通过"name"、"menuid"、"icon"对数据进行访问:

ListView{
 model:MenuEntryModel{ }
delegate:Item{
Column{
Text{text:name}
 Text{text:icon}
}
}
} 

如果仅为二维表提供数据,那么根据以上几个接口函数的名称就可以简单的实现数据供给View视图,其中:

int SqlMenuEntry::rowCount(const QModelIndex &parent) const
 {
 return mRecords.size();
} int SqlMenuEntry::columnCount(const QModelIndex &parent) const {  return 1;  //QML不使用列获取数据,默认返回一列,不返回1例的话,View控件会认为表是空表,不获取数据 } QModelIndex SqlMenuEntry::index(int row, int column, const QModelIndex &parent) const {   if((row >= 0)&&(row < mRecords.size()))   {     return createIndex(row,column);   }   return QModelIndex();  //返回一个无效的空索引 } QModelIndex SqlMenuEntry::parent(const QModelIndex &child) const {   return QModelIndex(); //二维表中的行没有parent节点 } QVariant SqlMenuEntry::data(const QModelIndex &index, int role) const {   if(index.isValid)   {    return mRecords[index.row()][role];   } } 

mRecords中的数据可以按需求生成,如通过QSqlQuery组件从数据库服务器获取,获取添加数据:

 QHash row;
 row[nameRole] = "name1";
row[iconRole] = "icon1";
mRecords.append(row); 

实现后的model类可以通过

qmlRegisterType("com.limutech.tv",1,0,"MenuEntryModel");

进行注册,注册后的类可以在QML生成实例:

 import com.limutech.tv 1.0
 MenuEntryModel{
id:menuEntryModel
}
ListView{
model:menuEntryModel
...
} 

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不为空的情况,同时,模型应该可以存储树状数据,在下一节我将继续分享层次模型的实现方式和涉及数据修改的一些实现。

Model (一) QML中的数据访问组件如ListView、TableView、GridView通常使用ListModel做为数据提供者,这种应用有相当大局限...

  在qt中,用到最多就是model/view的结构来表示数据层及表示层的关系。model用于给view提供数据。那如何来实现一个简单的树形model呢。

  实现一个自己的model需要重载以下的方法:

[cpp] view plain copy

 

 图片 1图片 2

  1. QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;  
  2. bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);  
  3. int rowCount(const QModelIndex &parent = QModelIndex()) const;  
  4. int columnCount(const QModelIndex &parent = QModelIndex()) const<pre name="code" class="cpp">QVariant headerData(int section, Qt::Orientation orientation,  
  5.                         int role = Qt::DisplayRole) const;  
  6. bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value,  
  7.                        int role = Qt::EditRole);  
  8. QModelIndex index(int row, int column,  
  9.                               const QModelIndex &parent = QModelIndex()) const;  
  10. QModelIndex parent(const QModelIndex &child) const;  
  11. virtual Qt::ItemFlags flags(const QModelIndex &index) const;  

 

下面通过一个小例子来说明每个方法的作用。想实现下面一个树形结构。

 

图片 3

既然实现一个model里面肯定得构造自己的数据结构。

 

[cpp] view plain copy

 

 图片 4图片 5

  1. class RowNode  
  2. {  
  3. public:  
  4.     RowNode() { m_pNode = NULL; }  
  5.     ~RowNode() {}  
  6. public:  
  7.     inline void setParent(RowNode *rowNode) { m_pNode = rowNode; }  
  8.     inline RowNode *parent() { return m_pNode; }  
  9. private:  
  10.     RowNode *m_pNode;  
  11. };  

model构造里

 

 

[cpp] view plain copy

 

 图片 6图片 7

  1. m_child1 = new RowNode();  
  2. m_child2 = new RowNode();  
  3. m_child2->setParent(m_child1);  

 

 

1)data方法:这个方法用于提供model所需要的各种数据。根据不同的index跟role返回不同的值。

 

[cpp] view plain copy

 

 图片 8图片 9

  1. QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;  
  2. {  
  3. <pre name="code" class="cpp">if (Qt::DisplayRole == role)  
  4.     {  
  5.         RowNode *pRowNode = static_cast<RowNode *>(index.internalPointer());  
  6.         if (m_child1 == pRowNode)  
  7.         {  
  8.             if (0 == index.column())  
  9.             {  
  10.                 return "Test";  
  11.             }  
  12.             else if (1 == index.column())  
  13.             {  
  14.                 return "Icon";  
  15.             }  
  16.             else if (2 == index.column())  
  17.             {  
  18.                 return "comboBox";  
  19.             }  
  20.         }  
  21.         else  
  22.         {  
  23.             if (0 == index.column())  
  24.             {  
  25.                 return "col0";  
  26.             }  
  27.             else if (1 == index.column())  
  28.             {  
  29.                 return "col1";  
  30.             }  
  31.             else  
  32.             {  
  33.                 return "col2";  
  34.             }  
  35.         }  
  36.     }  
  37.     else  
  38.         return QVariant();  
  39. }  

 

 

2)setData:这个方法用于设置model的各种数据,根据不同的index跟role的值.原理跟data一样,这里就不直接写了,直接返回True.

 

[cpp] view plain copy

 

 图片 10图片 11

  1. bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);  
  2. {  
  3.   return true;  
  4. }  

 

3)rowCount:用于设置行数。需要注意的是返回是指parent下面有几个子,而不是指整个TableView有多少行。因为显示树形的话,返回的RowCount只是指那个父结点有几个子。

 

[cpp] view plain copy

 

 图片 12图片 13

  1. int rowCount(const QModelIndex &parent = QModelIndex()) const;  
  2. {  
  3. <pre name="code" class="cpp">if (! parent.isValid())  
  4.     {  
  5.         return 1;  
  6.     }  
  7.     else  
  8.     {  
  9.         RowNode *pNode = static_cast<RowNode *>(parent.internalPointer());  
  10.         if (pNode == m_child1)  
  11.         {  
  12.             return 1;  
  13.         }  
  14.         else  
  15.         {  
  16.             return 0;  
  17.         }  
  18.     }  

 

 

本文由全球彩票平台发布于全球彩官网下载地址Web前端,转载请注明出处:自家从没会晤过

TAG标签: 全球彩票平台
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。