https://www.cnblogs.com/foohack/p/7531446.html
在Qt中如果是普通项目,GUI处理展现的数据量不大,一般用QTableWidget,QTreeWidget这样的控件就满足了,但是如果数据量行数达到了几万行,那么Widget的展示性能就偏差了。
Qt中提供了一种Model/View的编程方式来处理数据,也就是展示层和数据层分离,这样就解耦了。一旦Model的状态改变,它会自动渲染到View控件。这样的机制使得GUI可以展现大量的数据也不会卡顿。
为了处理数据的灵活性,我们用QStandardItemModel来做QTableView的Model层实现。因为以Table的形式展现,所以以下代码实现了,点击表头按列排序,点击行显式行的上下文菜单的功能。因为QTableView的默认
排序是按字符序列排序,所以得对QStandardItem进行子类化,并重载operator< 函数才能达到某些列用数值大小来排序。
因为是简单的Demo例子,QTableView是采用拖拽空间的方式拖到一个Widget里面的,该Wdiget类为ModelViewTable:

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

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

1 // CustomStandardItem.h
2 #pragma once
3
4 #include <QStandardItem>
5 #include <QString>
6
7 // 自定义数值排序
8 class CustomStandardItem : public QStandardItem
9 {
10 // Q_OBJECT
11
12 public:
13 CustomStandardItem();
14 CustomStandardItem(const CustomStandardItem& other);
15 CustomStandardItem(const QString &text);
16 CustomStandardItem & operator =(const CustomStandardItem& other);
17 ~CustomStandardItem();
18
19 public:
20 virtual bool operator<(const QStandardItem& other) const override;
21
22 };
23
24 //CustomStandardItem.cpp
25 #include "CustomStandardItem.h"
26
27 #include <QVariant>
28
29 CustomStandardItem::CustomStandardItem()
30 {
31 }
32
33 CustomStandardItem::CustomStandardItem(const CustomStandardItem& other)
34 :QStandardItem(other)
35 {
36
37 }
38
39 CustomStandardItem::CustomStandardItem(const QString &text)
40 :QStandardItem(text)
41 {
42
43 }
44
45 CustomStandardItem::~CustomStandardItem()
46 {
47 }
48
49 CustomStandardItem & CustomStandardItem::operator=(const CustomStandardItem& other)
50 {
51 QStandardItem::operator=(other);
52 return *this;
53 }
54
55 bool CustomStandardItem::operator<(const QStandardItem& other) const
56 {
57 const QVariant left = data(Qt::DisplayRole), right = other.data(Qt::DisplayRole);
58 // 第1到2列,全部采用浮点数的大小排序
59 if (column() == other.column() && other.column() >= 1 && other.column() <= 2)
60 {
61 return left.toDouble() < right.toDouble();
62 }
63
64 return QStandardItem::operator<(other);
65 }

以上代码就完全实现了Model/View 的Table编程。
references:
https://stackoverflow.com/questions/18421603/displaying-big-data-using-qt-table-view
https://stackoverflow.com/questions/4031168/qtableview-is-extremely-slow-even-for-only-3000-rows
https://doc.qt.io/archives/qq/qq07-big-tables.html
http://blog.csdn.net/woshiwlia/article/details/9141065
http://blog.csdn.net/u013255206/article/details/62235052
http://qimo601.iteye.com/blog/1539147
http://qimo601.iteye.com/blog/1530539
http://qimo601.iteye.com/blog/1530245