【问题标题】:QAbstractItemModel confused about index/parent and data functionsQAbstractItemModel 对索引/父级和数据函数感到困惑
【发布时间】:2012-10-23 12:16:09
【问题描述】:

我有以下简单的模型示例:

#include <QtGui/QApplication>
#include <QtGui/QTreeView>
#include <QAbstractItemModel>

class TestModel : public QAbstractItemModel
{
public:
    TestModel()
    {
        SetUpData();
    }

    virtual QModelIndex index(int row, int column, const QModelIndex& parent) const
    {
        if ( parent.isValid())
        {
            // child
            return createIndex( row, column, (void*)&mData[row].mChildren[column]);
        }
        // root
        return createIndex( row, column, (void*)&mData[row]);
    }

    virtual QModelIndex parent(const QModelIndex& child) const
    {
        ModelData* data = (ModelData*)child.internalPointer();

        // find out where "data" is in the mData vector structure
        for ( size_t i=0; i<mData.size(); ++i )
        {
            for ( size_t j=0; j<mData[i].mChildren.size(); ++j )
            {
                if ( &mData[i].mChildren[j] == data )
                {
                    // I think this is correct, return the parent row at col 0?
                    return createIndex( i, 0, (void*)&mData[i].mChildren[j]);
                }
            }
        }
        return QModelIndex();
    }

    virtual int rowCount(const QModelIndex& parent) const
    {
        if ( parent.isValid() )
        {
            // Per root node size
            return mData[parent.row()].mChildren.size();
        }

        // Root size
        return mData.size();
    }

    virtual int columnCount(const QModelIndex& parent) const
    {
        // The "parent" nodes should have two columns, the children should have 1
        if ( parent.isValid() )
        {
            // Root
            return 1;
        }
        // Children
        return 2;
    }

    virtual QVariant data(const QModelIndex& index, int role) const
    {
        if ( role == Qt::DisplayRole && index.isValid() )
        {
            if ( index.isValid() )
            {
                // I think col and row are the wrong way around, but will crash if swapped
                return mData[index.column()].mChildren[index.row()].mName;
            }
            else
            {
                // this never happens because "RootN" is never displayed
                return mData[index.column()].mName;
            }
        }
        return QVariant();
    }

private:
    // The "real" data that this Qt model is providing an interface to
    struct ModelData
    {
        QString mName;
        std::vector< ModelData > mChildren;
    };

    std::vector< ModelData > mData;

    void SetUpData()
    {
        for ( int i=0; i<3; ++i )
        {
            ModelData root;
            root.mName = "Root" + QString::number( i+1 );

            for ( int j=0; j<10; ++j )
            {
                ModelData node;
                node.mName = "Node" + QString::number( j+1 );
                root.mChildren.push_back( node );
            }
            mData.push_back( root );
        }
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    TestModel* model = new TestModel();
    QTreeView* tv = new QTreeView();

    tv->setModel( model );
    tv->show();

    int ret = a.exec();

    delete tv;
    delete model;

    return ret;
}

我在这里要做的是创建一个具有以下结构的模型:

Root1
 |-Node1-10
 |
Root2
 |-Node1-10
 |
Root3
 |-Node1-10

但是我最终得到了这个:

我真的很困惑索引/父级和数据应该如何工作。显然我不明白,因为我的输出不正确。

我认为例如 Root1、Node3 会导致 index 以 row = 0, col=2 调用,此时我使用 0,2 和指向该元素的指针调用 createIndex?

对于 parent(),如果 parent 有效,则返回 QModelIndex,因为这意味着它是 RootN 元素,如果它不是根元素,则返回 createIndex 以创建到 parent 的索引。

最后对于数据,我认为这只是返回给定行/列的 UI 的显示字符串?

【问题讨论】:

    标签: c++ qt qt4


    【解决方案1】:

    我认为例如,Root1,Node3 会导致索引 用 row = 0, col=2 调用,此时我用 0,2 调用 createIndex 以及指向该元素的指针?

    没有。您的树只有两列:col 0 显示树层次结构,col 1 再次显示标签。所以调用 col 2 是无效的。

    Root1, Node3 应该有一个 row=2 col=(1/2, whichever you want) 和一个等于 row=0, col=(1/2) 的父索引,但父索引无效(父索引无效意味着您位于根级别)。

    data(..) 返回的内容取决于 role 传递给它的内容,请参阅 documentation 了解您应该感兴趣的类型。

    【讨论】:

    • 我仍然对此感到困惑 - 你是说所有元素都应该被视为一个“平面”列表吗?例如:Root1 r0, c0, Node1 r1, c0, Node2 r2, c0, Root2 r3, c0 等?
    • 不,我认为您将树的“分支”与列混淆了。这些列显示模型中每个条目的不同数据位,每一行都是一个条目。树像分层表一样被寻址(每个单独都是平面的),要访问根元素,用户会将无效的父索引传递给index(..),要访问 Root2-Node1,您可以将根 2 的索引作为父节点传递,并且row=0 作为行(列就是您感兴趣的数据位)。
    • 我明白了,所以父节点无效的 QModelIndex r0, c0 将是 Root1,父节点为 r0 的 QModelIndex r0, c0 将是 Node1。并且 QModelIndex r2, c0 的父级为 r1, c0 将是 Node3 与父级 Root2?
    • 没错——一开始有点迷惑,但它的扩展性很好,可以适用于任何多层二维模型。
    猜你喜欢
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多