首页 > 其他分享 >Qt表格排序例子

Qt表格排序例子

时间:2024-03-04 10:00:10浏览次数:24  
标签:parent index const Qt 表格 int 排序 MItemModel

表格排序是Qt内建支持的,用起来很简单。只需要在QtCreator界面给QTableView或QTableWidget的SortingEnabled属性设置为true就行了。

本文将对这两种控件分别展示一下效果和一个自定义的排序例子。

一、QTableWidget

这个不需要任何代码,只需要设计界面时候启用排序就行了。下面直接截图:

二、QTableView

这种方式需要自己写代码,下面给出一个6行3列的例子。代码中QtTest是主窗口类,ui.tbContent是QTableView控件:

QtTest::QtTest(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    QStandardItemModel* myModel = new QStandardItemModel(ui.tbContent);
    myModel->setHorizontalHeaderLabels({ u8"列1", u8"列2", u8"列3", });
    myModel->setVerticalHeaderLabels({ u8"行1", u8"行2", u8"行3", u8"行4", u8"行5", u8"行6",});
    for (int i = 0; i < 6; i++)
    {
        QStandardItem *col1 = new QStandardItem();
        col1->setData(1000 + i, Qt::DisplayRole);
        myModel->setItem(i, 0, col1);
        QStandardItem *col2 = new QStandardItem();
        col2->setData(u8"dsaasf" + QString::number(i), Qt::DisplayRole);
        myModel->setItem(i, 1, col2);
        QStandardItem *col3 = new QStandardItem();
        col3->setData(32.123f + 2.5f * i, Qt::DisplayRole);
        myModel->setItem(i, 2, col3);
    }
    ui.tbContent->setSortingEnabled(true);
    ui.tbContent->setModel(myModel);
}

Qt排序的原理是对Model中的数据排序,然后按照新顺序重新显示数据。程序运行之后的界面如下图:

三、自定义排序

在Qt帮助中没有说明默认的排序的细节。不同于标准库里的std::sort(...)直接说明了它引用的是operator<(...)函数。Qt没有这样说,所以大概率是不能重载operator<(...)函数实现对自定义数据的排序。那怎么让自定义的数据支持排序功能呢?放心,Qt提供了其它的方式实现自己的排序功能。就是

  • 继承QAbstractItemModel并实现它的sort(...)函数,或者;
  • 用QSortFilterProxyModel包含你的Model然后实现其lessThan(...)函数,这个代理模型功能非常强大除了排序之外还支持数据查找过滤的功能。

下面将给出一个例子阐述如何自定义排序。该例子使用第一种方法。作者也是第一次做这个功能,对下方代码是否地道的把握不是很大,可能有些不合理之处。主要是QAbstractTableModel里的虚函数很多是默认空函数,所以不太清楚它们的功能和使用时机。比如:下方的函数beginResetModel()和endResetModel()什么时候使用Qt帮助也没说的很明确。这里就认为只要Model中的数据改变就调用。头文件:

class QStandardItem;

class MItemModel : public QAbstractTableModel
{
    Q_OBJECT

public:
    struct MyDataType
    {
        int type;
    };

public:
    MItemModel(QObject* parent = 0);
    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;

private:
    void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;

private:
    QVector<QVector<QStandardItem*>> datas;
};

Q_DECLARE_METATYPE(MItemModel::MyDataType);

class MyDataDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    MyDataDelegate(QObject* parent = 0);
    QString displayText(const QVariant &value, const QLocale &locale) const override;
};

CPP文件:

MItemModel::MItemModel(QObject* parent) : 
    QAbstractTableModel(parent)
{
}

MItemModel::~MItemModel()
{
    for (auto& item : datas)
    {
        qDeleteAll(item);
    }
}

QModelIndex MItemModel::index(int row, int column, const QModelIndex &parent) const
{
    return createIndex(row, column, nullptr);
}

int MItemModel::rowCount(const QModelIndex &parent) const
{
    return datas.size();
}

int MItemModel::columnCount(const QModelIndex &parent) const
{
    auto maxv = std::max_element(datas.begin(), datas.end(), 
        [](const QVector<QStandardItem*>& x, const QVector<QStandardItem*>& y) { return x.size() < y.size(); });
    return maxv->size();
}

QVariant MItemModel::data(const QModelIndex &index, int role) const
{
    const QVector<QStandardItem*>& rowData = datas[index.row()];
    if (index.column() < rowData.size() && rowData[index.column()])
    {
        return rowData[index.column()]->data(role);
    }
    return QVariant();
}

bool MItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    int r = index.row();
    int c = index.column();
    if (r >= datas.size())
    {
        datas.resize(r + 1);
    }
    if (c >= datas[r].size())
    {
        datas[r].resize(c + 1);
    }
    if (!datas[r][c])
    {
        datas[r][c] = new QStandardItem;
    }
    datas[r][c]->setData(value, role);
    return true;
}

/* 这是行头和列头 */
QVariant MItemModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole)
    {
        if (orientation == Qt::Orientation::Horizontal)
        {
            QString header = u8"列";
            return header + QString::number(section + 1);
        }
        if (orientation == Qt::Orientation::Vertical)
        {
            QString header = u8"行";
            return header + QString::number(section + 1);
        }
    }
    return QVariant();
}

void MItemModel::sort(int column, Qt::SortOrder order)
{
    if (column != 0)
    {
        /* Qt默认为空,点击其他列是不会排序的 */
        QAbstractTableModel::sort(column, order);
        return;
    }
    beginResetModel();
    /* 这里使用的是选择排序 */
    int count = rowCount();
    for (int i = 0; i < count; i++)
    {
        int maxi = i;
        MyDataType maxv = data(index(i, column), Qt::DisplayRole).value<MyDataType>();
        for (int j = i + 1; j < count; j++)
        {
            MyDataType curr = data(index(j, column), Qt::DisplayRole).value<MyDataType>();
            if ((curr.type < maxv.type) ^ (order == Qt::DescendingOrder))
            {
                maxv = curr;
                maxi = j;
            }
        }
        if (maxi != i)
        {
            std::swap(datas[maxi], datas[i]);
        }
    }
    endResetModel();
}

/////////////////////////////////////////////////////////////////////////////////////////

MyDataDelegate::MyDataDelegate(QObject* parent) : 
    QStyledItemDelegate(parent)
{
}

QString MyDataDelegate::displayText(const QVariant &value, const QLocale &locale) const
{
    MItemModel::MyDataType data = value.value<MItemModel::MyDataType>();
    return u8":" + QString::number(data.type);
}

主函数中初始化。代码中的QtTest是主窗口类,ui.tvContent是QTableView类:

QtTest::QtTest(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    
    MItemModel* myModel = new MItemModel(ui.tvContent);
    for (int i = 0; i < 6; i++)
    {
        myModel->setData(myModel->index(i, 0), QVariant::fromValue<MItemModel::MyDataType>({ 2 + i }), Qt::DisplayRole);
        myModel->setData(myModel->index(i, 1), u8"实例", Qt::DisplayRole);
        myModel->setData(myModel->index(i, 2), 324 + i, Qt::DisplayRole);
    }
    ui.tvContent->setModel(myModel);
    ui.tvContent->setItemDelegateForColumn(0, new MyDataDelegate(ui.tvContent));
    ui.tvContent->setSortingEnabled(true);
}

下面是运行时候的截图:

 

标签:parent,index,const,Qt,表格,int,排序,MItemModel
From: https://www.cnblogs.com/mengxiangdu/p/17952113

相关文章

  • 147. 对链表进行插入排序(中)
    目录题目题解优化题目给定单个链表的头head,使用插入排序对链表进行排序,并返回排序后链表的头。插入排序算法的步骤:插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在......
  • 力扣80.删除排序数组中的重复项 II
    题目:给你一个有序数组nums,请你删除重复出现的元素,使得出现次数超过两次的元素只出现两次,返回删除后数组的新长度。实现方法:使用map计数,用快慢指针方法,快指针不断加一,慢指针在计数小于出现次数时加一,再将快指针指向的数赋给慢指针指向的数。funcremoveDuplicates(nums......
  • Qt/C++音视频开发67-保存裸流加入sps/pps信息/支持264/265裸流/转码保存/拉流推流
    一、前言音视频组件除了支持保存MP4文件外,同时还支持保存裸流即264/265文件,以及解码后最原始的yuv文件。在实际使用过程中,会发现部分视频文件保存的裸流文件,并不能直接用播放器播放,查阅资料得知原来是缺少sps/pps信息,监控行业的rtsp/rtmp/录像mp4文件都是会带的,所以很少遇到这个......
  • pyqt5中多线程爬虫
       设立爬虫Class,继承pyqt5中的Thread函数中使用普通线程  整体代码:importsysimportpandasaspdimportjson,requests,time,threadingfromPyQt5.QtWidgetsimportQMainWindow,QApplication,QVBoxLayout,QMessageBoxfromui.ui_testimportUi_MainWind......
  • QTabWidget的高度取决于当前选项卡的高度
    QTabWidget的高度自适应当前选项卡的高度,可以通过设置其他选项卡的QSizePolicy为Ignored,connect(ui->tabWidget,SIGNAL(currentChanged(int)),this,SLOT(updateSizes(int)));voidMainWindow::updateSizes(intindex){for(inti=0;i<ui->tabWidget->count();i++)......
  • 第十一届蓝桥杯试题E:排序
    目录题目分析验证代码题目对一个字符串,对它进行冒泡排序使其为升序,例如:对于lan,排序成aln需要交换一次(只能交换相邻的两个字母),对于qiao,排序成aioq就需要交换4次。请找出冒泡排序时恰好需要交换100次的字符串,如果有多个字符串满足条件,则找出最短的那个,如果有多个满足条件而且......
  • 快速排序
    1.概念快速排序算法是对冒泡排序算法的一种改进算法,在当前所有内部排序算法中,快速排序算法被认为是最好的排序算法之一。2.基本思想快速排序的基本思想:通过一趟排序将待排序的序列分割为左右两个子序列,左边的子序列中所有数据都比右边子序列中的数据小,然后对左右两个子序列继......
  • PyQt入门教程(版本1)
    第1章PyQt5开发环境搭建和配置PyQt5工具可以快速实现简单的界面开发,包括界面设计、布局管理以及业务逻辑实现(信号与槽)。简单说就是使用PyQt5工具可以快速画一个控件摆放整齐、界面整洁有序、布局合理的界面。本文内容本文主要第1节PyQt5环境搭建和配置。主要内容包括:[!TIP......
  • Qt 16位和32位高低位转换
    一、16位高低位转换1quint16highAndLowConversion_16(quint16data)2{3return((data&ox00ff)<<8)|(data>>8);4} 二、32位高低位转换1quint32highAndLowConversion_32(quint32data)2{3return((data&0x0000ffff)<<......
  • C# MiniExcel 导入和导出表格数据
    C#MiniExcel导入和导出表格数据1.首先从NuGet包里下载MIniExcel文件引入然后下面是一段Api控制器导入的代码导入导出的表格用.xlsx或.xls工作表///<summary>///上传文件到服务器端///</summary>///<paramname="formFile"></param>///<returns></returns>[......