Qt5中表格处理大数据量

在Qt中如果是普通项目,GUI处理展现的数据量不大,一般用QTableWidget,QTreeWidget这样的控件就满足了,但是如果数据量行数达到了几万行,那么Widget的展示性能就偏差了。

Qt中提供了一种Model/View的编程方式来处理数据,也就是展示层和数据层分离,这样就解耦了。一旦Model的状态改变,它会自动渲染到View控件。这样的机制使得GUI可以展现大量的数据也不会卡顿。

为了处理数据的灵活性,我们用QStandardItemModel来做QTableView的Model层实现。因为以Table的形式展现,所以以下代码实现了,点击表头按列排序,点击行显式行的上下文菜单的功能。因为QTableView的默认

排序是按字符序列排序,所以得对QStandardItem进行子类化,并重载operator< 函数才能达到某些列用数值大小来排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// ModelViewTable.h
#pragma once
 
#include <QtWidgets/QWidget>
#include "ui_ModelViewTable.h"
 
class QStandardItemModel;
class QMenu;
 
class ModelViewTable : public QWidget
{
    Q_OBJECT
 
public:
    ModelViewTable(QWidget *parent = Q_NULLPTR);
    void generateDataSet();
    void addRowRecord(int row);
 
    void setColumnItem(int row, int column, QString ip);
 
public slots:
    void slotShowContextMenu(const QPoint& point);
private:
    Ui::ModelViewTableClass ui;
    QStandardItemModel * m_model;
    QMenu* m_contextMenu;
};
 
// ModelViewTable.cpp
#include "ModelViewTable.h"
 
#include <QStandardItemModel>
#include <QStandardItem>
#include <QString>
#include <QMenu>
#include <QAction>
 
#include "CustomStandardItem.h"
 
ModelViewTable::ModelViewTable(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
 
    //////////////////////////设置表头/////////////////////
    m_model = new QStandardItemModel(this);
    m_model->setColumnCount(3);
    m_model->setHeaderData(0, Qt::Horizontal, QStringLiteral("终端IP"));
    m_model->setHeaderData(1, Qt::Horizontal, QStringLiteral("CPU使用率"));
    m_model->setHeaderData(2, Qt::Horizontal, QStringLiteral("内存使用率"));
 
    ui.tableView->resizeColumnsToContents(); // 自适应列宽
    ui.tableView->setSortingEnabled(true); // 可以按列来排序
    ui.tableView->setModel(m_model);
    ui.tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignHCenter);
    ui.tableView->horizontalHeader()->setFont(QFont("Times",10,QFont::Bold));
 
    ui.tableView->setSelectionBehavior(QAbstractItemView::SelectRows); //整行选中
    ui.tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);// 表格单元格为只读
    ui.tableView->setContextMenuPolicy(Qt::CustomContextMenu); // 可以自定义右键菜单
 
    m_contextMenu = new QMenu(this);
    QAction *processAct = new QAction(QStringLiteral("进程列表信息"),m_contextMenu);
    QAction *windowAppsAct = new QAction(QStringLiteral("窗口应用列表信息"),m_contextMenu);
    m_contextMenu->addAction(processAct);
    m_contextMenu->addAction(windowAppsAct);
 
    connect(ui.tableView, SIGNAL(customContextMenuRequested(const QPoint&)),
        this, SLOT(slotShowContextMenu(const QPoint&)));
 
 
}
 
void ModelViewTable::generateDataSet()
{
    for (int i = 0; i < 3000; ++i)
    {
        addRowRecord(i);
    }
}
 
void ModelViewTable::addRowRecord(int row)
{
    // 每行3列
    QString ip = QString("%1.%2.%3.%4").arg(192).arg(168).arg(1).arg(row);
    setColumnItem(row, 0, ip);
 
    QString cpu = QString("%1").arg((row * 10) % 100);
    setColumnItem(row, 1, cpu);
 
    QString mem = QString("%1").arg((row * 12)  % 100);
    setColumnItem(row, 2, mem);
 
}
 
void ModelViewTable::slotShowContextMenu(const QPoint& point)
{
    QModelIndex index = ui.tableView->indexAt(point);
    if (index.isValid())
    {
        m_contextMenu->exec(QCursor::pos());
    }
}
 
void ModelViewTable::setColumnItem(int row, int column, QString ip)
{
    m_model->setItem(row, column, new CustomStandardItem(ip));
    m_model->item(row, column)->setTextAlignment(Qt::AlignCenter);
}

  因为需要实现自定义的数值排序,所以要继承QStandardItem,并覆盖其中的相关函数:

复制代码
//   CustomStandardItem.h
#pragma once

#include <QStandardItem>
#include <QString>

//  自定义数值排序
class CustomStandardItem : public QStandardItem
{
   // Q_OBJECT

public:
    CustomStandardItem();
    CustomStandardItem(const CustomStandardItem& other);
    CustomStandardItem(const QString &text);
    CustomStandardItem & operator =(const CustomStandardItem& other);
    ~CustomStandardItem();

public:
    virtual bool operator<(const QStandardItem& other) const override;

};

//CustomStandardItem.cpp
#include "CustomStandardItem.h"

#include <QVariant>

CustomStandardItem::CustomStandardItem()
{
}

CustomStandardItem::CustomStandardItem(const CustomStandardItem& other)
    :QStandardItem(other)
{

}

CustomStandardItem::CustomStandardItem(const QString &text)
    :QStandardItem(text)
{

}

CustomStandardItem::~CustomStandardItem()
{
}

CustomStandardItem & CustomStandardItem::operator=(const CustomStandardItem& other)
{
    QStandardItem::operator=(other);
    return *this;
}

bool CustomStandardItem::operator<(const QStandardItem& other) const
{
    const QVariant left = data(Qt::DisplayRole), right = other.data(Qt::DisplayRole);
    //   第1到2列,全部采用浮点数的大小排序
    if (column() == other.column() && other.column() >= 1 && other.column() <= 2)
    {
        return left.toDouble() < right.toDouble();
    }

    return QStandardItem::operator<(other);
}
复制代码

出处:https://www.cnblogs.com/foohack/p/7531446.html

posted @   浅笑19  阅读(423)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示