代码之家  ›  专栏  ›  技术社区  ›  Basti An

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

  •  0
  • Basti An  · 技术社区  · 7 年前

    我想在qabstractemmodel的GUI中显示一个项目及其角色。在手册中我只能找到如何显示整个模型。

    显示单个项可以工作,但是当模型中的数据更改时,图形用户界面中的数据不会更新。

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

    模型中的对象:

    #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
    

    模型标题:

    #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:

    #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中的单个项,如下所示:

     Text {
           text: dataSourceModel.data(dataSourceModel.index(88,0),259).toFixed(decimalplaces)
          }
    

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

    我试图从Q object派生模型中的对象,以使用Q_INVOKABLE,但从QObject派生时,无法编译该对象。C:\Q t\5.10.0\mingw53_32\include\QtCore\qlist.h:435:Fehler:use of deleted function'DataSourceObject::DataSourceObject(const DataSourceObject&)' if(QTypeInfo::isLarge | | QTypeInfo::isStatic)n->v=新T(T);

                                                               ^
    
    0 回复  |  直到 7 年前
        1
  •  1
  •   eyllanesc    7 年前

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

    一种可能的解决方案是在加载程序旁边使用中继器,如果行是指定的行,则该加载程序将创建一个项。

    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_属性。