1. 程式人生 > >Qt5中表格處理大資料量

Qt5中表格處理大資料量

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