使用什么而不是QStringList?

时间:2017-09-21 14:17:14

标签: c++ qt qml

我是Qt的新手,所以我不确定要使用什么。

我以为我会QStringList提供给QStringListModel并将其显示在ListView

但是,现在我需要将QStringList除以2种类型的值。所以,我需要字符串+一些typeId,而不仅仅是一个字符串,但QStringList仅用于一维列表。

任何人都可以就尝试实施此方法的最佳方式提出建议吗?

2 个答案:

答案 0 :(得分:0)

解决方案是使用QAbstractListModel子类作为 Qt Quick 模型。模型的基类示例(为方便起见,我使用它):

// abstractobjectlistmodel.h
#pragma once

#include <QtCore>

struct AbstractObjectListModel
        : public QAbstractListModel
{

    explicit AbstractObjectListModel(QObject * const parent = Q_NULLPTR)
        : QAbstractListModel{parent}
    { ; }

    int rowCount(QModelIndex const & parent = {}) const Q_DECL_OVERRIDE Q_DECL_FINAL
    {
        Q_UNUSED(parent);
        return items.count();
    }

    QVariant data(QModelIndex const & index, const int role = Qt::DisplayRole) const Q_DECL_OVERRIDE Q_DECL_FINAL
    {
        if (!index.isValid()) {
            return {};
        }
        switch (role) {
        case Qt::UserRole : {
            return QVariant::fromValue(items[index.row()].data());
        }
        default : {
            return {};
        }
        }
    }

    QHash< int, QByteArray > roleNames() const Q_DECL_OVERRIDE Q_DECL_FINAL
    {
        auto roleNames = QAbstractListModel::roleNames();
        roleNames.insert(Qt::UserRole, "modelData");
        return roleNames;
    }

    Q_INVOKABLE
    virtual
    QObject * get(int row) const
    {
        if (row < 0) {
            return {};
        }
        if (row >= rowCount()) {
            return {};
        }
        return items[row];
    }

    void remove(int row, int count = 1)
    {
        Q_ASSERT(count > 0);
        Q_ASSERT(row >= 0);
        Q_ASSERT(row + count <= rowCount());
        beginRemoveRows({}, row, row + count - 1);
        while (0 < count) {
            items.takeAt(row)->deleteLater();
            --count;
        }
        endRemoveRows();
    }

    void clear()
    {
        if (!items.isEmpty()) {
            remove(0, rowCount());
        }
    }

protected :

    ~AbstractObjectListModel() Q_DECL_OVERRIDE Q_DECL_EQ_DEFAULT; // derived classes should not meant to be manipulated polymorphically

    QList< QPointer< QObject > > items;

    void insert(int row, QObject * const item)
    {
        item->setParent(this);
        beginInsertRows({}, row, row);
        items.insert(row, item);
        endInsertRows();
    }

    void append(QObject * const item)
    {
        insert(rowCount(), item);
    }

};

但是需要覆盖get来访问项目Q_PROPERTY属性(除了动态属性):

// type of element
class Project
        : public QObject
{

    Q_OBJECT

    Q_PROPERTY(QString name MEMBER name NOTIFY nameChanged)
    Q_PROPERTY(QString path MEMBER path NOTIFY pathChanged)

public :

    Project(QString name, QString path,
            QObject * const parent = Q_NULLPTR)
        : QObject{parent}
        , name{name}
        , path{path}
    { ; }

Q_SIGNALS :

    void nameChanged(QString name);
    void pathChanged(QString path);

private :

    QString name;
    QString path;

};

// custom model
class ProjectsListModel
        : public AbstractObjectListModel
{

    Q_OBJECT

public :

    explicit ProjectsListModel(QObject * const parent = Q_NULLPTR)
        : AbstractObjectListModel{parent}
    { ; }

    void appendProject(QString name, QString path)
    {
        AbstractObjectListModel::append(::new Project{name, path});
    }

    Q_INVOKABLE
    Project *
    get(int row) const Q_DECL_OVERRIDE
    {
        return qobject_cast< Project * >(AbstractObjectListModel::get(row));
    }

};

在使用之前,需要使用qmlRegisterType< ProjectsListModel >();注册具体模型。 Projectdelegate的{​​{1}}类的属性可以通过highlight的成员获得。

另一个例子:

modelData

除了通过struct TimeZoneModel Q_DECL_FINAL : public QAbstractListModel { Q_OBJECT public : explicit TimeZoneModel(QObject * const parent = Q_NULLPTR) : QAbstractListModel{parent} { ; } int rowCount(QModelIndex const & parent = {}) const Q_DECL_OVERRIDE { Q_UNUSED(parent); return timeZoneIds.count(); } QVariant data(QModelIndex const & index, const int role = Qt::DisplayRole) const Q_DECL_OVERRIDE { if (!index.isValid() || (role > Qt::UserRole + 4)) { return {}; } QTimeZone timeZone{timeZoneIds[index.row()]}; if (!timeZone.isValid()) { return {}; } return roleData(timeZone, role); } QHash< int, QByteArray > roleNames() const Q_DECL_OVERRIDE { auto roleNames = QAbstractListModel::roleNames(); int i = Qt::UserRole; for (const auto role : {"modelData", "id", "comment", "name", "country"}) { roleNames.insert(i++, role); } return roleNames; } Q_INVOKABLE QByteArray get(int row) const { if (row < 0) { return {}; } if (row >= rowCount()) { return {}; } return timeZoneIds[row]; } private : QVariant roleData(QTimeZone const & timeZone, int role = Qt::UserRole) const { switch (role) { case Qt::UserRole : { QVariantMap modelData; const auto names = roleNames(); while (++role < Qt::UserRole + 5) { modelData.insert(QString::fromUtf8(names[role]), roleData(timeZone, role)); } return modelData; } case Qt::UserRole + 1: { return QString::fromUtf8(timeZone.id()); } case Qt::UserRole + 2 : { return timeZone.comment(); } case Qt::UserRole + 3 : { return timeZone.displayName(QTimeZone::StandardTime); } case Qt::UserRole + 4 : { return QLocale::countryToString(timeZone.country()); } default : { return {}; } } } const QByteArrayList timeZoneIds = QTimeZone::availableTimeZoneIds(); }; 的字段(modelDatamodelData.id等)进行访问外,所有符号都可以直接访问(即modelData.commentid等)在comment的{​​{1}}和delegate上下文中。

模型highlightListView,可以直接注入全局范围而不会出现任何性能缺陷:

TimeZoneModel

答案 1 :(得分:-1)

如果您需要包含QString和任何其他类型的字典,我建议您使用

  QMap<QString, YourType> myMap;

这里有一些用法示例:

QMap<int, QString> myMap;
myMap.insert(1,"A");
myMap.insert(2,"B");
myMap[3] = "C";

foreach(int i, myMap.keys()) qDebug() << myMap[i];