博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Qt之QHeaderView自定义排序(终极版)
阅读量:4352 次
发布时间:2019-06-07

本文共 7635 字,大约阅读时间需要 25 分钟。

简述

本节主要解决自定义排序衍生的第二个问题-将整形显示为字符串,而排序依然正常。

下面我们介绍三种方案:

  1. 委托绘制
  2. 用户数据
  3. 辅助列

很多人也许会有疑虑,平时都用delegate来绘制各种按钮、图标、图形等操作,它还能排序?当然,它本身是不会排序的,但他的高级用法之一就是-辅助排序。

委托绘制

效果

这里写图片描述

QStyledItemDelegate

我们可以通过设置显示的文本,然后调用QStyle的drawControl来进行ViewItem的绘制。绘制之后,数据源中的数据依然是qint64的,而我们看到的是绘制之后的文本-QString类型,这样QSortFilterProxyModel默认排序(根据源数据排序)就可以满足我们的要求了。

void SortDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const{    QStyleOptionViewItem viewOption(option);    initStyleOption(&viewOption, index);    if (option.state.testFlag(QStyle::State_HasFocus))        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;    // 进行大小转换    if (index.column() == FILE_SIZE_COLUMN)    {        qint64 bytes = index.data().toLongLong();        viewOption.text = bytesToGBMBKB(bytes) ;        QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &viewOption, painter, viewOption.widget);    }    else    {        QStyledItemDelegate::paint(painter, viewOption, index);    }}

眼见不一定为实

通过效果图我们也可以很明显的看出来,其实内部的数据并不是界面显示的字符串,而是原始的qint64类型的数据。

pTableView->setMouseTracking(true);connect(pTableView, SIGNAL(entered(QModelIndex)), this, SLOT(showToolTip(QModelIndex)));void MainWindow::showToolTip(const QModelIndex &index){    if (!index.isValid())        return;    int nColumn = index.column();    if ((nColumn == FILE_SIZE_COLUMN))        QToolTip::showText(QCursor::pos(), index.data().toString());}

用户数据

QAbstractTableModel

显示在界面的数据为DisplayRole中的数据,我们可以看到已经通过bytesToGBMBKB转化为字符串,这时我们可以通过设置UserRole添加用户数据将源数据存储起来。

// 表格项数据QVariant TableModel::data(const QModelIndex &index, int role) const{    if (!index.isValid())        return QVariant();    int nRow = index.row();    int nColumn = index.column();    FileRecord record = m_recordList.at(nRow);    switch (role)    {    case Qt::TextColorRole:        return QColor(Qt::white);    case Qt::TextAlignmentRole:        return QVariant(Qt::AlignLeft | Qt::AlignVCenter);    case Qt::DisplayRole:    {        if (nColumn == FILE_NAME_COLUMN)        {            return record.strFileName;        }        else if (nColumn == DATE_TIME_COLUMN)        {            return record.dateTime;        }        else if (nColumn == FILE_SIZE_COLUMN)        {            return bytesToGBMBKB(record.nSize);        }        return "";    }    case Qt::UserRole:    {        // 新增代码        if (nColumn == FILE_SIZE_COLUMN)            return record.nSize;    }    default:        return QVariant();    }    return QVariant();}

QSortFilterProxyModel

根据用户源数据进行排序。

bool SortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const{    if (!source_left.isValid() || !source_right.isValid())        return false;    if ((source_left.column() == FILE_SIZE_COLUMN) && (source_right.column() == FILE_SIZE_COLUMN))    {        // 这里我们所取得数据是用户源数据        QVariant leftData = sourceModel()->data(source_left, Qt::UserRole);        QVariant rightData = sourceModel()->data(source_right, Qt::UserRole);        if (leftData.canConvert
() && rightData.canConvert
()) { return leftData.toLongLong() < rightData.toLongLong(); } } return QSortFilterProxyModel::lessThan(source_left, source_right);}

辅助列

效果

这里写图片描述

QAbstractTableModel

设置辅助数据

#define FILE_NAME_COLUMN 0          // 文件名#define DATE_TIME_COLUMN 1          // 修改日期#define FILE_SIZE_COLUMN 2          // 文件大小#define FILE_SIZE_HIDDEN_COLUMN 3   // 文件大小隐藏列,显示为字节// 列数int TableModel::columnCount(const QModelIndex &parent) const{    Q_UNUSED(parent);    return 4;}// 设置表格项数据bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role){    if (!index.isValid())        return false;    int nColumn = index.column();    FileRecord record = m_recordList.at(index.row());    switch (role)    {    case Qt::DisplayRole:    {        if (nColumn == FILE_NAME_COLUMN)        {            record.strFileName = value.toString();        }        else if (nColumn == DATE_TIME_COLUMN)        {            record.dateTime = value.toDateTime();        }        // 新增代码        else if ((nColumn == FILE_SIZE_COLUMN) || (nColumn == FILE_SIZE_HIDDEN_COLUMN))        {            record.nSize = value.toLongLong();        }        m_recordList.replace(index.row(), record);        emit dataChanged(index, index);        // 新增代码        if ((nColumn == FILE_SIZE_COLUMN) || (nColumn == FILE_SIZE_HIDDEN_COLUMN))        {            int nSizeColumn = (nColumn == FILE_SIZE_COLUMN) ? FILE_SIZE_HIDDEN_COLUMN : FILE_SIZE_COLUMN;            QModelIndex sizeIndex = this->index(index.row(), nSizeColumn);            emit dataChanged(sizeIndex, sizeIndex);        }        return true;    }    default:        return false;    }    return false;}// 表格项数据QVariant TableModel::data(const QModelIndex &index, int role) const{    if (!index.isValid())        return QVariant();    int nRow = index.row();    int nColumn = index.column();    FileRecord record = m_recordList.at(nRow);    switch (role)    {    case Qt::TextColorRole:        return QColor(Qt::white);    case Qt::TextAlignmentRole:        return QVariant(Qt::AlignLeft | Qt::AlignVCenter);    case Qt::DisplayRole:    {        if (nColumn == FILE_NAME_COLUMN)        {            return record.strFileName;        }        else if (nColumn == DATE_TIME_COLUMN)        {            return record.dateTime;        }        else if (nColumn == FILE_SIZE_COLUMN)        {            return bytesToGBMBKB(record.nSize);        }        // 新增代码        else if (nColumn == FILE_SIZE_HIDDEN_COLUMN)        {            return record.nSize;        }        return "";    }    default:        return QVariant();    }    return QVariant();}// 表头数据QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const{    switch (role)    {    case Qt::TextAlignmentRole:        return QVariant(Qt::AlignLeft | Qt::AlignVCenter);    case Qt::DisplayRole:    {        if (orientation == Qt::Horizontal)        {            if (section == FILE_NAME_COLUMN)                return QStringLiteral("名称");            if (section == DATE_TIME_COLUMN)                return QStringLiteral("修改日期");            if (section == FILE_SIZE_COLUMN)                return QStringLiteral("大小");            // 新增代码            if (section == FILE_SIZE_HIDDEN_COLUMN)                return QStringLiteral("大小(字节)");        }    }    default:        return QVariant();    }    return QVariant();}

QSortFilterProxyModel

这里对第三列进行排序,因为第三列的数据是字符串(当然,也可以反转换),所以使用的辅助列数据,获取字节大小后进行对比。

bool SortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const{    if (!source_left.isValid() || !source_right.isValid())        return false;    if ((source_left.column() == FILE_SIZE_COLUMN) && (source_right.column() == FILE_SIZE_COLUMN))    {        // 获取辅助列索引        QModelIndex sizeLeftIndex = sourceModel()->index(source_left.row(), FILE_SIZE_HIDDEN_COLUMN);        QModelIndex sizeRightIndex = sourceModel()->index(source_right.row(), FILE_SIZE_HIDDEN_COLUMN);        QVariant leftData = sourceModel()->data(sizeLeftIndex);        QVariant rightData = sourceModel()->data(sizeRightIndex);        if (leftData.canConvert
() && rightData.canConvert
()) { return leftData.toLongLong() < rightData.toLongLong(); } } return QSortFilterProxyModel::lessThan(source_left, source_right);}

隐藏辅助列

一般来说,辅助列(数据)只对我们处理数据有帮助,而不直接显示在界面上,所以我们可以将其隐藏pTableView->setColumnHidden(FILE_SIZE_HIDDEN_COLUMN, true);

总结

小小一个排序居然也有这么多门道,真是条条大路通罗马,通过这几节的分享,想必大家对排序有了更深入的了解,更多的知识请参考官方文档。

转载于:https://www.cnblogs.com/itrena/p/5938373.html

你可能感兴趣的文章
SQL Server2012完全备份、差异备份、事务日志备份和还原操作
查看>>
Flash动画播放
查看>>
springmvc+mybatis+dubbo+zookeeper 分布式架构
查看>>
HDUOJ-----Computer Transformation
查看>>
HDUOJ-----2838Cow Sorting(组合树状数组)
查看>>
自定义控件之---抽屉式弹窗控件.
查看>>
一款纯css3实现的机器人看书动画效果
查看>>
加班与效率
查看>>
轻量级Modal模态框插件cta.js
查看>>
MyEclipse下SpringBoot+JSP整合过程及踩坑
查看>>
重定向和管道
查看>>
实验五
查看>>
STL学习笔记(第二章 C++及其标准程序库简介)
查看>>
Operator_countByValue
查看>>
Java 日期往后推迟n天
查看>>
Web应用漏洞评估工具Paros
查看>>
Git 和 Github 使用指南
查看>>
20180925-4 单元测试
查看>>
mysql的数据存储
查看>>
[转载] Activiti Tenant Id 字段释疑
查看>>