简述

在Windows中我们经常会遇到表头排序,比如可以对文件按照名称、修改日期、类型、大小进行排序,方便我们统一的归类查找。

Qt中,我们可以通过点击表头来对QTableView或QTreeView等一系列高级视图进行排序,对于一般的数据来说-比如:int、QString等,简单的几句代码就可以搞定,因为Qt内部做了很好的排序处理,但是一般情况下,我们需要处理一些特殊格式的数据,这时,我们就不得不自己处理,以达到理想的效果。

效果

自定义数据

定义各列数据及结构体

#define FILE_NAME_COLUMN 0   // 文件名
#define DATE_TIME_COLUMN 1 // 修改日期
#define FILE_SIZE_COLUMN 2 // 文件大小 typedef struct FileRecord
{
QString strFileName; // 文件名
QDateTime dateTime; // 修改日期
qint64 nSize; // 文件大小
} fileRecord;

QAbstractTableModel

源码

自定义模型

TableModel::TableModel(QObject *parent)
: QAbstractTableModel(parent)
{ } TableModel::~TableModel()
{ } // 更新表格数据
void TableModel::updateData(QList<FileRecord> recordList)
{
m_recordList = recordList;
beginResetModel();
endResetModel();
} // 行数
int TableModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent); return m_recordList.count();
} // 列数
int TableModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent); return 3;
} // 设置表格项数据
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)
{
record.nSize = value.toLongLong();
} m_recordList.replace(index.row(), record);
emit dataChanged(index, index);
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 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("大小");
}
}
default:
return QVariant();
} return QVariant();
} // 表格可选中
Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return QAbstractItemModel::flags(index); Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; return flags;
}

接口说明

  • updateData

    主要用于更新数据,刷新界面。

  • data

    用来显示数据,根据角色(颜色、文本、对齐方式、选中状态等)判断需要显示的内容。

  • setData

    用来设置数据,根据角色(颜色、文本、对齐方式、选中状态等)判断需要设置的内容。

  • headerData

    用来显示水平/垂直表头的数据。

  • flags

    用来设置单元格的标志(可用、可选中、可复选等)。

使用

QTableView *pTableView = new QTableView(this);
TableModel *pModel = new TableModel(this);
QSortFilterProxyModel *pProxyModel = new QSortFilterProxyModel(this);
// 设置数据源模型
pProxyModel->setSourceModel(pModel);
pTableView->setModel(pProxyModel);
// 设置可排序
pTableView->setSortingEnabled(true);
// 设置按照文件名升序排列
pTableView->sortByColumn(FILE_NAME_COLUMN, Qt::AscendingOrder); // 构造数据,更新界面
QList<FileRecord> recordList; // 获取随机值
QTime time = QTime::currentTime();
qsrand(time.msec() + time.second()*1000); for (int i = 0; i < 5; ++i)
{
int nIndex = qrand()%20 + 1;
int nHour = qrand()%24;
int nMinute = qrand()%60;
int nSecond = qrand()%60;
int nBytes = qrand()%100000; QDateTime dateTime(QDate(2016, 5, 1), QTime(nHour, nMinute, nSecond)); FileRecord record;
record.strFileName = QString("Name %1.cpp").arg(nIndex);
record.dateTime = dateTime;
record.nSize = nBytes; recordList.append(record);
}
pModel->updateData(recordList);

思考

  1. 细心地童鞋可能会发现,当点击表头(文件名)的时候,如果按照升序排列时,顺序依次是:Name 14、Name 19、Name 4、Name 8、Name 9,降序则相反。为什么呢?

    其实这个很好理解,因为文件名所在的列显示的数据类型为QString,而QString排序是按照第一个字母开始比较,直至最后一个字母,例如:Name 19和Name 4,首先比较Name是相同的,当比较1和4(注意这里不是按照整形比较19和4)的时候,发现1比4小,所以Name 19排在Name 4之前。

  2. 对于文件大小的显示,一般情况下,我们显示的是KB、MB、GB等单位,而不会显示字节,那么按照1的说法,在这种情况下,升序排列时,10 K 就会排在8 K之前了,所以我们应该避免这种问题。

上面所述的简单排序谁都会,如何把前面的数据按照字符串比较,而后面的数据按照整形比较呢?如何将整形显示为字符串,而排序依然正常呢?这都是我们下节要分享的精彩内容,请持续关注!

Qt之QHeaderView排序的更多相关文章

  1. Qt之QHeaderView自定义排序(获取正确的QModelIndex)

    简述 前几节中分享过关于自定义排序的功能,貌似我们之前的内容已经可以很好地解决排序问题了,但是,会由此引发一些很难发现的问题...比如:获取QModelIndex索引错误. 下面,我们先来实现一个整行 ...

  2. Qt之QHeaderView自定义排序(终极版)

    简述 本节主要解决自定义排序衍生的第二个问题-将整形显示为字符串,而排序依然正常. 下面我们介绍三种方案: 委托绘制 用户数据 辅助列 很多人也许会有疑虑,平时都用delegate来绘制各种按钮.图标 ...

  3. Qt之QHeaderView自定义排序(QSortFilterProxyModel)

    简述 对以上节的排序,我们衍伸了两点: 把一个字符串前面的数据按照字符串比较,而后面的数据按照整形比较. 将整形显示为字符串,而排序依然正常呢. 为了分别描述,这里我们先解决问题1. 简述 效果 处理 ...

  4. Qt之QHeaderView添加复选框

    简述 前面分享了QTableView中如何添加复选框.本节主要介绍QTableView中的表头-QHeaderView添加复选框的功能,下面以水平表头为例,垂直表头类似! 简述 效果 QHeaderV ...

  5. Qt之QHeaderView加入复选框

    简述 前面分享了QTableView中怎样加入复选框. 本节主要介绍QTableView中的表头-QHeaderView加入复选框的功能,以下以水平表头为例.垂直表头相似! 简述 效果 QHeader ...

  6. 《Qt 实战一二三》

    简介 "我们来自Qt分享&&交流,我们来自Qt Quick分享&&交流",不管你是笑了,还是笑了,反正我们是认真的.我们就是要找寻一种Hold不住的 ...

  7. QRowTable表格控件-支持hover整行、checked整行、指定列排序等

    目录 一.开心一刻 二.嘴一嘴 三.效果展示 四.浅谈实现 五.自定义数据源 1.data函数 2.flags函数 六.自定义视图 1.目的 2.问题分析 七.测试 八.相关文章 原文链接:QRowT ...

  8. QRowTable表格控件(五)-重写表头排序、支持第三次单击恢复默认排序

    目录 一.原生表格 二.效果展示 三.实现方式 1.排序列定制 2.排序交互修改 四.相关文章 原文链接:QRowTable表格控件(五)-重写表头排序.支持第三次单击恢复默认排序 一.原生表格 开发 ...

  9. 【转】Qt数据库总结

    转自:http://blog.chinaunix.net/uid-25201977-id-3014100.html #include <QtSql>QT += sql QSqlDataba ...

随机推荐

  1. 关于面向对象--oop

    这两天在做大数据方面的项目看到关于job作业调度的设计,扣了两天了,感触良多,记下来做个反省. 这是一个精简版的图,其中还有一些没有划到,其实到这里目前对我来说已经足够了. 看完图之后进行分析,我只抛 ...

  2. mongodb 主从服务器

    @set mongod=..\bin\mongod.exe set keyFile=key.key if not exist %keyFile% ( echo 123456>%keyFile% ...

  3. php随机数怎么获取?一个简单的函数就能生成

    小美女建了一个站,有些页面相似度比较高,想添加一些字段来实现差异化,比如用php随机数生成从10到100之间随机一个数字.其实会php的朋友几十个字符就能实现了,如下代码所示,简单吧?10代表最小值, ...

  4. css两个form不换行,两个div并排代码

    1.form不换行通过table布局实现 <table> <tr> <td> <form method="get" action=&quo ...

  5. VS2010中出现无法嵌入互操作类型

    针对word或excel操作时,出现VS2010中,无法嵌入互操作类型“……”,请改用适用的接口的解决方法 问了度娘,解决方法如出一辙:选中项目中引入的dll,鼠标右键,选择属性,把“嵌入互操作类型” ...

  6. 免安装jdk 和 免安装tomcat

    免安装tomcat 运行的时候要执行免安装的 jdk,可以进行如下设置. 在 startup.bat 里加上这么一句, set "JAVA_HOME=C:\jdk1.6.0_43"

  7. DB2对年份的处理Year()

    public DataSet GetCustomerAllocListByQC(CustomerAllocQueryDataContract aQC) { StringBuilder sql = ne ...

  8. php截取字符串中的关键字,并高亮显示

    <?php $str = "hahaceshi测试一下关键字高亮显示,以及长字符串截取的问题!"; $key = "关键字"; $r = sub_key_ ...

  9. C#播放声音

    [DllImport("winmm.dll")] public static extern long PlaySound(String fileName, long a, long ...

  10. Linux command: usermod -- 改变用户状态

    应用举例: 1. usermod -g newuser newuser force use GROUP as new primary group. 一般时候是默认的,也是必须的(不能更改).2. 指定 ...