首页 > 编程知识 正文

c语言字符串数组定义,c语言指针数组

时间:2023-05-06 07:26:21 阅读:54954 作者:1276

参考资料:

参照视图模型,QML作为视图,c中的对象作为模型,实现业务逻辑和接口的分离。

公开各个c类的属性

这样,QML就可以直接访问在上下文中注册的c类实例,并在QML中注册的全局,具体是在QQuickView或engine中注册。 例如,自定义包含data属性的Name类。

类定义

暴露于QML访问的类需要特殊的定义。

/*name.h*/

#包含

从class name : publicqobject//q object继承

{

Q_OBJECT//QObject宏

q _ property (qstringdatareaddatawritesetdatanotifydatachanged )。

公共:

name(qobject*parent=nullptr ); //默认构造函数

名称(qstring _ name; //构造函数

QString data () const; //READ接口

语音设置(const qstring _ data );//写入接口

signals:

已更改qstring data (; //NOTIFY信号(不需要实现) ) ) ) )。

隐私:

QString m_data; //专用属性

(;

可以在项目上单击鼠标右键-新建文件-C Class中添加新类,从QObject继承,然后自动将文件添加到项目中。

warning :不要直接在CPP文件中定义类。 由于Q_OBJECT宏需要moc处理,而非. h文件不会进行moc处理,因此在编译时会出现“无法识别的符号”错误

q _ property (qstringdatareaddatawritesetdatanotifydatachanged )。

此行中的代码定义了暴露于QML访问的接口。 这里提供的对象是QString,READ接口是名为data的函数,WRITE接口是名为setData的函数,通告接口用于绑定通知。 只有设置了NOTIFY接口,QML才能自动与c属性同步。 这里的命名方式最好和默认值统一。

类的实现

/*name.cpp*/

#include 'name.h '

name :3360 name (q object * parent (: q object (parent ) ) ) ) ) ) ) )。

//默认构造函数

}

name:3360name(qstring_data ) :m_data(_data ) () ) )。

//初始化自定义构造函数、专用对象m_data

}

QString Name:data () const

{

返回m _ data; //READ接口实现,返回专用对象

}

void name :3360 setdata (常数字符串_数据) )。

{

if(_data!=m_data(//write接口已实现,将更新并发出m_data

m_data=_data;

emit数据更改(;

}

}

在setData中,必须确定数据是否已更新,并且只有在数据实际发生更改时才需要发出信号。 否则,会有无限递归的风险。

注册到上下文

然后实例化Name类并在上下文中注册它。 注册必须在读取. qml文件之前完成。

/*main.cpp*/

namea_name(test );

QQmlApplicationEngine engine;

qml context * root contex=engine.root context (; 获取engine的根上下文

根上下文- setcontextproperty (' name ',qvariant :3360 from value (a _ name ); //注册

engine.load (qurl (qstring literal (' qrc :/main.qml ' ) )

用QML导入

QML允许您读取接口返回的属性,直接为属性赋值,并接收属性的更改。

/*main.qml*/

Rectangle {

文本{

text:name.data //相当于调用名为name.data ()的接口

建立到连接//通告接口的连接

target: name

o

nDataChanged:{//对应NOTIFY接口

console.log("data has beed changed!");

}

}

}

Button {

text:"changeData"

onClicked: {

name.data = "hasChanged!";

}

}

}

当点击按钮时,Text 的文字会发生变化,同时控制台输出 “data has beed changed!”,闭环达成。

Connections 用来监听事件,监听的 target 是定义了 NOTIFY 的对象(注意 onDataChanged 这个 event handler 的驼峰命名法和原 NOTIFY 定义时的命名。

使用 QList 作为 Model

更常见的需求是,暴露一组对象的属性,并通过 QML 中的 View 来自动渲染。例如我们把 Name 类放进一个 QList 列表,作为 Model 传给 QML 中的 ListView。

/*main.cpp*/

QList NameList;

NameList.append(new Name("name1"));

NameList.append(new Name("name2"));//增加两个Name对象在数组中

QQmlApplicationEngine engine;

QQmlContext* rootContex = engine.rootContext();//拿到engine的根上下文

rootContex->setContextProperty("nameList", QVariant::fromValue(NameList));//注册

engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

/*main.qml*/

ListView{

width: parent.width

height: 300

model: nameList

delegate: Rectangle {

height: 30

width: parent.width

color: "#000000"

Text {

text: model.data //调用每个对象的data()方法

color: "#FFFFFF"

Connections{

target: model //监听这个对象

onDataChanged:{

console.log("changed!");

}

}

}

}

}

这样就得到了一个列表渲染。此时渲染出来的列表在注册到上下文的时候就已经确定,列表项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

color: "#999999"

Text {

text: model.modelData.name //name是每个item的属性

color: "#FFFFFF"

}

Button {

anchors.right: parent.right

width: 50

height: 30

font.family: "FontAwesome"

font.pixelSize: 24

text: "uf019"

onClicked: {

model.modelData.name = textField.text;//可以直接给item修改属性

}

}

}

}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。