Qt模型视图编程中重写rowCount函数需要注意的地方

先从实际中遇到的一个问题开始:要自定义一个QListModel,有两种选择:
方式一:继承自QAbstractListModel
方式二:继承自QAbstractItemModel
二者都可以实现,但有差别。

请问:在方式一中

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;

这个函数应该怎么写才对?
大家都知道这个函数的作用是返回列表中一共有多少行,但是这个函数怎么写才对?

举例:

int ChatListModel::rowCount(const QModelIndex &parent) const
{
    // For list models only the root node (an invalid parent) should return the list's size. For all
    // other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
    if (parent.isValid())
        return 0;

    return static_cast<int>(m_items.size());
}

里面的注释是Qt自动帮我们加上的,这里的if判断条件中容易出错。
我们看这个函数
qabstractitemmodel.h文件中

class Q_CORE_EXPORT QModelIndex
{
//..其余代码省略
	inline QModelIndex() noexcept : r(-1), c(-1), i(0), m(nullptr) {}
	inline bool isValid() const noexcept { return (r >= 0) && (c >= 0) && (m != nullptr); }

private:
//..其余代码省略
	int r, c;
	quintptr i;
    const QAbstractItemModel *m;
};

对于一个QModelIndex(),来说,它的行和列都是默认值-1,而m也是nullptr,isValid()当然应该返回false

自定义的QListView的model中,传入的父项应该都是QModelIndex(),因为列表是没有层级关系的,只有1层。

if (parent.isValid())
        return 0;

这个对于自定义的QListView的model来说,if判断条件永远为false,这个return 0永远不会执行。

对于方式二:
我们继承自QAbstractItemModel来实现一个自定义的QListView的model,这种方式相对复杂一点,但是也更加灵活。
看到Qt Creator自动帮我们加的代码:

int MyListModel::rowCount(const QModelIndex &parent) const
{
    if (!parent.isValid())
        return 0;

    // FIXME: Implement me!
}

if (!parent.isValid())这的判断条件就不同了,对于一个自定义的QListView的model来说,这里应该返回的是列表的行数,而不是0,这点没注意到,就会坑了,发现你是QListView是空的,原因就是这里出了问题。

同理继承自QAbstractTableModel实现一个自定义的TableModel
Qt Creator帮我们加的代码是:

int MyTableModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    // FIXME: Implement me!
}

这个和继承自QAbstractListModel类似。

猜想:可能是Qt Creator觉得,如果你继承自QAbstractItemModel来实现一个Model,可能是要实现一个自定义的有层级关系的树形Model,所以它那里的判断条件是上面说的那样。而一般的列表Model和表格Model是没有层级关系的,其父节点都是QModelIndel(),一个isValid()判断条件返回false的项。

附:
Qt Creator中

右键->add New
Qt模型视图编程中重写rowCount函数需要注意的地方_第1张图片
Qt模型视图编程中重写rowCount函数需要注意的地方_第2张图片
选择哪种继承哪个基类来实现自定义Model。

你可能感兴趣的:(Qt爬坑实录)