QTableWidget用QAbstractItemModel来实现大量数据的加载

QTableWidget是使用QStandardItemModel作为数据模型的,如果要实现大量数据的加载并支持排序,可以考虑继承QAbstractItemModel,自定义一个数据模型来替代QStandardItemModel。下面是一个示例代码:

#include <QApplication>
#include <QTableWidget>
#include <QHeaderView>
#include <QScrollBar>
#include <QTimer>
#include <QAbstractItemModel>

const int ROWS_PER_PAGE = 100; // 每页显示的行数
const int TOTAL_ROWS = 10000; // 数据总行数

class MyTableModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    MyTableModel(QObject *parent = nullptr)
        : QAbstractItemModel(parent)
        , m_rows(TOTAL_ROWS)
    {
        for (int i = 0; i < m_rows.size(); ++i) {
            QVector<QVariant> row;
            row.append(QString("Item %1").arg(i));
            row.append(qrand() % 100);
            m_rows[i] = row;
        }
    }

    QVariant data(const QModelIndex &index, int role) const override
    {
        if (!index.isValid())
            return QVariant();
        if (role == Qt::DisplayRole) {
            return m_rows[index.row()][index.column()];
        }
        return QVariant();
    }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override
    {
        if (parent.isValid())
            return 0;
        return m_rows.size();
    }

    int columnCount(const QModelIndex &parent = QModelIndex()) const override
    {
        if (parent.isValid())
            return 0;
        return 2;
    }

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
    {
        if (parent.isValid() || row < 0 || row >= m_rows.size() || column < 0 || column >= 2)
            return QModelIndex();
        return createIndex(row, column);
    }

    QModelIndex parent(const QModelIndex &index) const override
    {
        Q_UNUSED(index);
        return QModelIndex();
    }

    Qt::ItemFlags flags(const QModelIndex &index) const override
    {
        if (!index.isValid())
            return Qt::NoItemFlags;
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    }

    QVariant headerData(int section, Qt::Orientation orientation, int role) const override
    {
        if (role != Qt::DisplayRole)
            return QVariant();
        if (orientation == Qt::Horizontal) {
            switch (section) {
            case 0:
                return QString("Name");
            case 1:
                return QString("Value");
            default:
                return QVariant();
            }
        }
        return QVariant();
    }

    void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override
    {
        if (column < 0 || column >= 2)
            return;
        if (order == Qt::AscendingOrder)
            std::sort(m_rows.begin(), m_rows.end(), [&](const QVector<QVariant>& row1, const QVector<QVariant>& row2) {
                return row1[column] < row2[column];
            });
        else
            std::sort(m_rows.begin(), m_rows.end(), [&](const QVector<QVariant>& row1, const QVector<QVariant>& row2) {
                return row1[column] > row2[column];
            });
        emit layoutChanged();
    }

private:
    QVector<QVector<QVariant>> m_rows;
};

class TableWidget : public QTableWidget
{
    Q_OBJECT
public:
    TableWidget(QWidget *parent = nullptr)
        : QTableWidget(parent)
        , m_rowCount(0)
        , m_currentPage(0)
    {
        setSortingEnabled(true); // 开启排序功能
        horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 自适应列宽
        verticalScrollBar()->setSingleStep(ROWS_PER_PAGE); // 设置滚动条步长

        m_model = new MyTableModel(this);
        setModel(m_model);

        connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(onScrollBarValueChanged(int)));
        QTimer::singleShot(0, this, SLOT(loadData())); // 延时加载数据
    }

private slots:
    void onScrollBarValueChanged(int value)
    {
        if (value == verticalScrollBar()->maximum()) {
            // 如果滚动到底部了,尝试加载下一页数据
            if ((m_currentPage + 1) * ROWS_PER_PAGE < TOTAL_ROWS) {
                ++m_currentPage;
                loadData();
            }
        }
    }

    void loadData()
    {
        int rowsToAdd = qMin(TOTAL_ROWS - m_rowCount, ROWS_PER_PAGE);
        for (int i = m_rowCount; i < m_rowCount + rowsToAdd; ++i) {
            QVector<QVariant> row;
            row.append(QString("Item %1").arg(i));
            row.append(qrand() % 100);
            m_model->beginInsertRows(QModelIndex(), i, i);
            m_model->m_rows.append(row);
            m_model->endInsertRows();
        }
        m_rowCount += rowsToAdd;
    }

private:
    int m_rowCount; // 已加载的行数
    int m_currentPage; // 当前页数
    MyTableModel *m_model;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TableWidget w;
    w.show();
    return a.exec();
}

#include "main.moc"

在这个示例代码中,我们自定义了一个MyTableModel类,继承自QAbstractItemModel,并且实现了data、rowCount、columnCount、index、parent、flags、headerData和sort等函数。其中,sort函数是用来支持排序功能的,利用std::sort对数据进行排序并发射layoutChanged信号来更新表格。

因为MyTableModel是一个自定义的数据模型,所以在TableWidget中需要通过setModel函数来设置表格的数据模型,并且在loadData函数中使用beginInsertRows和endInsertRows函数来动态地更新模型中的数据。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值