设为首页 加入收藏

TOP

QML与C++数据绑定教程(二)
2018-03-22 08:49:22 】 浏览:546
Tags:QML 数据 绑定 教程
!"); } } } } }

这样就得到了一个列表渲染。此时渲染出来的列表在注册到上下文的时候就已经确定,列表项Name动态的修改会体现到界面上,但是动态增删数组元素不会发生变化(因为 QList 本身并没有 NOTIFY 接口)。

注册类型到QML上下文中

当前的 Name 类已经完备的实现了注册到 QML 上下文中的接口,所以可以在 C++ 中调用

qmlRegisterType
  
   ("com.myapp.name", 1, 0, "Name");
//包名,大版本号,小版本号,类型名

  

进行注册,在 QML 文件中加入引用后就可以直接使用 Name 类以及其属性。

import com.myapp.name 1.0

Name {
    data: "Foo"
}

封装一组数据暴露给 QML

与直接放入 QList 不同,通过更高级的封装可以实现动态绑定的列表渲染。避免使用QQmlListProperty这个方法,文档有问题且相关资料少

线性表封装为抽象列表类型

朴素的 C++ 线性表类型(数组或者 Vector 模板类等等)通过封装就可以成为被 QML 直接访问的 Model。封装成的类可以是继承自 QAbstractListModel 或者更复杂的 QAbstractTableModel。关键在于继承后实现几个作为 QML 调用接口的虚函数(完整的虚函数表参照文档):

/*必须实现的虚函数*/
int rowCount(const QModelIndex &parent) const;//返回数据行数
QVariant data(const QModelIndex &index, int role) const;//返回根据index和role请求的数据
QHash
  
    roleNames()  const;//返回数据别名

  

通过实现更多的虚函数可以完成更复杂的面向 QML 功能。

抽象类型定义

假定我们有一个 QList 内部的每个元素都是 Name 类型,注意 Name 已经完成了对 QML 访问所必须的封装。于是一个可在QML中渲染的 Name 类型的线性表封装成的类应该长这样:

/*namelist.h*/
#include 
  
   
#include 
   
     #include 
    
      #include "name.h" class NameList : public QAbstractListModel { Q_OBJECT public: enum datatype { type1 = 0 }; NameList(QObject *parent); NameList(){ addName("test1"); addName("test2"); } /*必须实现的虚函数 供QML引擎调用*/ int rowCount(const QModelIndex &parent) const;//返回数据行数 QVariant data(const QModelIndex &index, int role) const;//返回所求的数据 QHash
     
       roleNames() const;//返回数据别名 /*其他接口*/ Q_INVOKABLE bool pushData(QString a_name); private: QList
      
        _NameList;//被封装的数组 }; 
      
     
    
   
  

首先类内声名了一个枚举类型,每个类型对应数据项中被访问的一个属性。Name 类只有一个 data 属性,所以只定义了一种类型。

然后是rowCount(const QModelIndex &parent),QML引擎查询列表时通过这个函数取得列表项的数量。

QVariant data(const QModelIndex &index, int role)是QML引擎用来访问每个列表项的接口,访问的时候会通过index表明索引,role表明查找的属性(对应枚举类型datatype)。

QHash roleNames()返回role的别名(暂时不是特别重要)。

抽象类型实现

/*namelist.cpp*/
#include 
  
   
#include 
   
     #include "namelist.h" NameList::NameList(QObject *parent) { } int NameList::rowCount(const QModelIndex &parent) const { return _NameList.count();//返回私有列表数据量 } QVariant NameList::data(const QModelIndex &index, int role) const { qDebug() << role; int row = index.row();//index包含.row()和.count()等属性 return QVariant::fromValue(_NameList.at(row));//数据项包装成QVariant返回 } QHash
    
      NameList::roleNames() const { QHash
     
       d; d[datatype::type1] = "Foo";//给tpye1设置别名 return d; } bool NameList::pushData(QString a_name) { Name* cache = new Name(a_name); beginInsertRows(QModelIndex(), _NameList.count(), _NameList.count()); _NameList.append(cache); endInsertRows(); return true; } 
     
    
   
  

列表被封装以后,在进行增删的时候需要先调用beginInsertRows(QModelIndex, int , int),第一个参数对应 Model 数据,通过QModelIndex()得到这个Model的虚拟rootItem;后两个参数代表所改动的行数范围:例如在第二行加入3个数据,则两个参数分别是\( (2, 4) \). 修改完成后还要调用endInsertRows()声名修改完毕。

注册到上下文

/*main.cpp*/
NameList theList;//实例化一个类

QQmlApplicationEngine engine;
QQmlContext* rootContex = engine.rootContext();
rootContex->setContextProperty("namelist", &theList);//注册到上下文
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

在 QML 中读取

/*main.qml*/
ListView{
    width: parent.width
    height: 300
    model: namelist //把抽象类作为model
    delegate: Rectangle {
        height: 30
        width: parent.width
        c
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇唯一的雪花(Unique snowflakes,U.. 下一篇C++怎么定义未知元素个数的数组?

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目