首页 > 解决方案 > Qt C++ ListView使用QAbstractItemModel追加数据定位不准确

问题描述

使用自定义数据模型,如果当前浏览位置超过100个,添加数据后会定位到第100个位置;

列表模型:

header:
#include <QAbstractListModel>

class ChatListItemModal: public QAbstractListModel {
    Q_OBJECT
public:
    explicit ChatListItemModal(QObject *parent = 0);
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    void addChatItems(QVector<QString> items);
private:
    QVector<QString> chatItem;
};

cpp:
#include "chatlistitemmodel.h"

ChatListItemModal::ChatListItemModal(QObject *parent): QAbstractListModel(parent)
{

}
int ChatListItemModal::rowCount(const QModelIndex &parent) const
{
    return (parent.isValid() && parent.column() != 0) ? 0 : this->chatItem.size();
}
QVariant ChatListItemModal::data(const QModelIndex &index, int role) const {
    if (index.isValid() && index.row() < chatItem.size() && index.row() >= 0 && role == Qt::DisplayRole)
       return QVariant::fromValue<QString>(chatItem.at(index.row()));
    return QVariant();
}
void ChatListItemModal::addChatItems(QVector<QString> items)
{
    if (items.isEmpty())
        return;
    beginInsertRows(QModelIndex(),
                    chatItem.size(),
                    chatItem.size() + items.size() - 1
                    );
    chatItem.append(items);
    endInsertRows();
}

QScrollView:

header :
#include "chatlistitemdelegate.h"
#include "chatlistitemmodel.h"

#include <QListView>
#include <QVector>

class ChatListScrollView: public QListView
{
    Q_OBJECT

public:
    ChatListScrollView(QWidget *parent = nullptr);
    void render();
    void onAddChat(const int count = 0);
private:
    ChatListItemModal *listModal;
    ChatListItemDelegate *listItemDelegate;
};

cpp:

#include "chatlistscrollview.h"


ChatListScrollView::ChatListScrollView(QWidget *parent): QListView(parent)
{
    render();
}
void ChatListScrollView::render()
{
    setFrameShape(QListView::NoFrame);
    setResizeMode(QListView::ResizeMode::Fixed);
    setLayoutMode(QListView::LayoutMode::Batched);
    setFlow(QListView::TopToBottom);
    setMovement(QListView::Static);
    setViewMode(QListView::ListMode);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
    setAutoScroll(true);
    setUniformItemSizes(true);
    viewport()->setAutoFillBackground(false);
    listItemDelegate = new ChatListItemDelegate(this);
    setItemDelegate(listItemDelegate);

    listModal = new ChatListItemModal(this);
    setModel(listModal);
    scrollToBottom();

}
// parent component trigger
void ChatListScrollView::onAddChat(const int count)
{
    int dataCount = listModal->rowCount();
    QVector<QString> list;
    for (int i = 0; i < count; ++i)
    {
        QString title = QStringLiteral("hello %1").arg(i + dataCount);
        list.push_back(title);
    }
    listModal->addChatItems(list);
}


感觉好像没有调用其他方法,data()中的输出好像是先拿到第100行的数据,然后再拿到剩下的数据。

感谢您的任何建议!

标签: cqt

解决方案


我虽然更像是一个真正的最小的、可编译的例子——它对我来说很好用:

class ChatListItemModel : public QAbstractListModel
{
public:
    int rowCount(const QModelIndex &) const override { return m_chatItem.count(); }
    QVariant data(const QModelIndex &index, int role) const override {
        if (index.isValid() && index.row() < m_chatItem.size() && index.row() >= 0 && role == Qt::DisplayRole)
            return m_chatItem.at(index.row());
        return QVariant();
    }
    void addChatItems(const QVector<QString> &items)
    {
        if (items.isEmpty())
            return;
        beginInsertRows(QModelIndex(),
                        m_chatItem.size(),
                        m_chatItem.size() + items.size() - 1
                        );
        m_chatItem.append(items);
        endInsertRows();
    }
    void addTwoMoreItems()
    {
        QVector<QString> items;
        for (int i = 1; i <= 2; ++i)
            items.push_back(QStringLiteral("New item %1").arg(i));
        addChatItems(items);
    }
private:
    QVector<QString> m_chatItem;
};

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    ChatListItemModel model;
    QVector<QString> items;
    for (int i = 1; i <= 99; ++i)
        items.push_back(QStringLiteral("Item %1").arg(i));
    model.addChatItems(items);
    QListView view;
    view.setModel(&model);
    view.show();
    view.scrollToBottom();

    QTimer::singleShot(5000, &model, &ChatListItemModel::addTwoMoreItems);    
    return app.exec();
}

推荐阅读