首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用什么来代替QStringList?

用什么来代替QStringList?
EN

Stack Overflow用户
提问于 2017-09-21 22:17:14
回答 2查看 408关注 0票数 1

我是Qt的新手,所以我不知道该用什么。

我想我应该有一个QStringList给我的QStringListModel,并在ListView中显示它。

但是,现在我需要将QStringList分为两种类型的值。因此,我需要string +一些typeId,而不仅仅是一个string,但QStringList仅用于一维列表。

任何人都可以给出一个建议,什么是尝试实现这一点的最佳方式?

EN

回答 2

Stack Overflow用户

发布于 2017-09-23 00:25:52

解决方案是使用QAbstractListModel子类作为Qt快速模型。一个模型的基类示例(我使用它是为了方便):

代码语言:javascript
运行
复制
// 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属性(除了动态属性之外):

代码语言:javascript
运行
复制
// 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 >();注册具体的模型。在delegatehighlight中,可以通过modelData的成员获得modelData类的属性。

另一个例子:

代码语言:javascript
运行
复制
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();

};

除了经由modelData的字段(modelData.idmodelData.comment等)访问之外,在ListViewdelegatehighlight上下文中可以直接访问所有符号(即idcomment等)。

模型TimeZoneModelconst,可以直接注入全局作用域,没有任何性能缺陷:

代码语言:javascript
运行
复制
QQmlApplicationEngine engine;

TimeZoneModel timeZoneModel;
Q_SET_OBJECT_NAME(timeZoneModel);
qmlRegisterType< TimeZoneModel >();
const auto rootContext = engine.rootContext();
rootContext->setContextProperty(timeZoneModel.objectName(), &timeZoneModel);
票数 0
EN

Stack Overflow用户

发布于 2017-09-21 22:37:21

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

代码语言:javascript
运行
复制
  QMap<QString, YourType> myMap;

下面是一些用法示例:

代码语言:javascript
运行
复制
QMap<int, QString> myMap;
myMap.insert(1,"A");
myMap.insert(2,"B");
myMap[3] = "C";

foreach(int i, myMap.keys()) qDebug() << myMap[i];
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46346356

复制
相关文章

相似问题

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