我在上一篇文章已经写过三个方法用C++给qml传入自定义list,但是那三个方法都不支持数据的更新,也就是说C++这边的数据发生了改变,listview是不知道数据发生变化的。这样使用起来局限性很大,特别是一些有数据变化的场合,就没法使用了。下面介绍第四种方法,可以更新listview的数值。
整体思路是:
step1:根据自己的项目需求创建自定义数据结构
step2:创建数据模型
step3:将定义的数据模型传入qml
下面详细介绍每一步
class DeviceList {
public:
DeviceList(const QString &name, const QString &value, const QString unit);
QString name() const {
return m_name;
}
QString value() const {
return m_value;
}
QString unit()const {
return m_unit;
}
private:
QString m_name;
QString m_value;
QString m_unit;
};
这里定义了一个DeviceList类,里面有 name,value,unit三个数据成员。
数据模型必须具备两个条件:
1、必须继承QAbstractListModel这个类。目的是当数据发生变化时,能够自动的通知QML view。
2、由于会用到信号槽,所以要加入 Q_OBJECT宏
class DeviceListModel : public QAbstractListModel {
Q_OBJECT
public:
enum AnimalRoles {
nameRole = Qt::UserRole + 1,
valueRole,
nuitRole
};
DeviceListModel(QObject *parent = 0);
//目的是添加新的设备
void addDevice(const DeviceList &devicelist);
//返回list节点个数
int rowCount(const QModelIndex & parent = QModelIndex()) const;
//返回数据
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
protected:
//Returns the model's role names.
QHash roleNames() const;
private:
QList m_runTimeData;
};
DeviceListModel::DeviceListModel(QObject *parent)
: QAbstractListModel(parent) {
}
void DeviceListModel::addDevice(const DeviceList &deviceList) {
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_runTimeData << deviceList;
endInsertRows();
}
int DeviceListModel::rowCount(const QModelIndex & parent) const {
Q_UNUSED(parent);
return m_runTimeData.count();
}
QVariant DeviceListModel::data(const QModelIndex & index, int role) const {
if (index.row() < 0 || index.row() >= m_runTimeData.count())
return QVariant();
const DeviceList &deviceList = m_runTimeData[index.row()];
if (role == nameRole)
return deviceList.name();
else if (role == valueRole)
return deviceList.value();
else if (role == nuitRole)
return deviceList.unit();
return QVariant();
}
QHash DeviceListModel::roleNames() const {
QHash roles;
roles[nameRole] = "name";
roles[valueRole] = "value";
roles[nuitRole] = "unit";
return roles;
}
DeviceList::DeviceList(const QString &name, const QString &value, const QString unit)
: m_name(name), m_value(value), m_unit(unit) {
}
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
DeviceListModel model;
model.addDevice(DeviceList("ch1局放强度", "1000", "mV"));
model.addDevice(DeviceList("ch2局放强度", "500", "mV"));
model.addDevice(DeviceList("ch3局放强度", "800", "mV"));
model.addDevice(DeviceList("ch1局放能量", "10", "mW"));
model.addDevice(DeviceList("ch2局放能量", "20", "mW"));
model.addDevice(DeviceList("ch3局放能量", "15", "mW"));
QQmlApplicationEngine engine;
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("myModel", &model);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
id:page
Row{
id:tableTitle
Rectangle{
width:page.width/3
height:tableName.font.pixelSize
Text{
id:tableName
text:"测点名称"
anchors.centerIn: parent
}
}
Rectangle{
width:page.width/3
height:tableName.font.pixelSize
Text{
id:value
text:"测量值"
anchors.centerIn: parent
}
}
Rectangle{
width:page.width/3
height:tableName.font.pixelSize
Text{
id:unit
text:"单位"
anchors.centerIn: parent
}
}
}
ListView{
anchors.top: tableTitle.bottom
width: page.width
height: page.height-tableTitle.height
model:myModel
delegate: myDeleagta
Component{
id:myDeleagta
Row{
Rectangle{
width:page.width/3
height:tableName.font.pixelSize
Text{
text :name
anchors.centerIn: parent
}
}
Rectangle{
width:page.width/3
height:tableName.font.pixelSize
Text{
text:value
anchors.centerIn: parent
}
}
Rectangle{
width:page.width/3
height:tableName.font.pixelSize
Text{
text:unit
anchors.centerIn: parent
}
}
}
}
}
}
由于安卓不支持tableView,只用能listView自定义个tableView了