首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何显示QAbstractListModel的单个项目并在数据更改时更新Gui?

如何显示QAbstractListModel的单个项目并在数据更改时更新Gui?
EN

Stack Overflow用户
提问于 2019-04-16 02:18:03
回答 1查看 746关注 0票数 1

我想从QAbstractItemModel中显示单个项目及其在图形用户界面中的角色。在手册中,我只能找到如何显示整个模型。

显示单个项目是可行的,但是当模型中的数据发生更改时,GUI中的数据不会更新。

该模型在setData()函数中发出dataChanged()。

模型中的对象:

代码语言:javascript
复制
#ifndef DATASOURCEOBJECT_H
#define DATASOURCEOBJECT_H

#include <QString>
#include <QVariantMap>

class DataSourceObject
{
public:
    DataSourceObject(const int &id=0, const QString &name="", const QString &displayname="", const double &value=0.0);
    DataSourceObject(const QJsonObject &obj);
    int id() const;
    void setId(int id);

    QString name() const;
    void setName(const QString &name);

    QString unit() const;
    void setUnit(const QString &unit);

    double value() const;
    void setValue(double value);
    QVariantMap toMap() const;

private:
    int m_id;
    QString m_name;
    QString m_unit;
    double m_value;
};

#endif // DATASOURCEOBJECT_H

模型标头:

代码语言:javascript
复制
#ifndef DATASOURCEMODEL_H
#define DATASOURCEMODEL_H

#include "datasourceobject.h"
#include <QAbstractListModel>

class DataSourceModel : public QAbstractListModel
{
    Q_OBJECT

public:
    enum datasourceRoles {
        idRole = Qt::UserRole ,
        nameRole,
        unitRole,
        valueRole
    };

    explicit DataSourceModel(QObject *parent = nullptr);
    void addDataSourceObject(const DataSourceObject &dataSourceObject);
    Q_INVOKABLE QVariantMap get(int row) const;

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    Q_INVOKABLE QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::EditRole) override;
    Qt::ItemFlags flags(const QModelIndex& index) const override;
    QHash<int, QByteArray> roleNames() const override;
    //bool checkIndex(const QModelIndex &index) const;

private:
    QList<DataSourceObject> m_DataSourceObjects;
};

#endif // DATASOURCEMODEL_H

模型cpp:

代码语言:javascript
复制
#include "datasourcemodel.h"

DataSourceModel::DataSourceModel(QObject *parent)
    : QAbstractListModel(parent)
{
}

QVariantMap DataSourceModel::get(int row) const
{
    return m_DataSourceObjects[row].toMap();
}

void DataSourceModel::addDataSourceObject(const DataSourceObject &dataSourceObject)
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_DataSourceObjects << dataSourceObject;
    endInsertRows();
}
int DataSourceModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return m_DataSourceObjects.count();
}

QVariant DataSourceModel::data(const QModelIndex &index, int role) const
{
    if(index.row() < 0 || index.row() >= m_DataSourceObjects.count() || !index.isValid())
        return  QVariant();

    const DataSourceObject &dataSourceObject = m_DataSourceObjects[index.row()];
    if (role == idRole)
        return dataSourceObject.id();
    else if (role == nameRole)
        return dataSourceObject.name();
    else if (role == unitRole) {
        return dataSourceObject.unit();
    }
    else if (role == valueRole)
        return dataSourceObject.value();
    return QVariant();
}

bool DataSourceModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    DataSourceObject &dataSourceObject = m_DataSourceObjects[index.row()];
    if (data(index, role) != value) {
        if(role == idRole)
            dataSourceObject.setId(value.toInt());
        else if(role == nameRole)
            dataSourceObject.setName(value.toString());
        else if(role == unitRole)
            dataSourceObject.setUnit(value.toString());
        else if(role == valueRole)
            dataSourceObject.setValue(value.toDouble());
        emit dataChanged(index, index, QVector<int>() << role);
        return true;
    }
    return false;
}

Qt::ItemFlags DataSourceModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;

    return Qt::ItemIsEditable; // FIXME: Implement me!
}

QHash<int, QByteArray> DataSourceModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[idRole] = "id";
    roles[nameRole] = "name";
    roles[unitRole] = "unit";
    roles[valueRole] = "value";
    return  roles;
}

我尝试访问QML中的单个项目,如下所示:

代码语言:javascript
复制
 Text {
       text: dataSourceModel.data(dataSourceModel.index(88,0),259).toFixed(decimalplaces)
      }

这显示了数据的角色259(valueRole),但文本在更改时不会更新。

我试图从QObject派生模型内部的对象,以使用Q_INVOKABLE,但当从QOBject派生时,我无法编译it.C:\Qt\5.10.0\mingw53_32\include\QtCore\qlist.h:435: Fehler:使用已删除的函数'DataSourceObject::DataSourceObject(const DataSourceObject&)‘if (QTypeInfo::isLarge || QTypeInfo::isStatic) n->v = new T(t);

代码语言:javascript
复制
                                                           ^
EN

回答 1

Stack Overflow用户

发布于 2019-04-16 08:40:29

文本不会更新,因为您只复制值,但组件之间没有绑定。

一种可能的解决方案是在Loader旁边使用Repeater,如果行是指定的行,该Loader将创建一个项目。

代码语言:javascript
复制
Component {
    id: textcomponent
    Text {
        text: value.toFixed(decimalplaces)
    }
}
Repeater{
    model: dataSourceModel
    Loader{
        property real value: model.value
        sourceComponent: index == 88 ? textcomponent: null
    }
}

一个完整的例子,你可以找到here

另一种可能的解决方案是使项88特别成为Q_PROPERTY。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55695104

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档