• Qt5中表格处理大数据量


    在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

  • 相关阅读:
    在 macOS High Sierra 10.13 搭建 PHP 开发环境
    给你的网站免费配置上 HTTPS 证书
    将 MacOS 默认的 PHP 版本升级到 7.*
    System.Data.SqlClient.SqlException: 'Incorrect syntax near 'OFFSET'.
    IIS7/8 HTTP Error 500.19 错误 0x80070021 错误代码:0x8007000d
    http error 502.5
    信用卡逾期了怎么办 ?逾期记录“修复”的两大原则
    APP多开教程
    lua调用不同lua文件中的函数
    Lua 用指定字符或字符串分割输入字符串,返回包含分割结果的数组
  • 原文地址:https://www.cnblogs.com/foohack/p/7531446.html
Copyright © 2020-2023  润新知