Qt自定义表头实现过滤功能的方法
1. 写在前面
过滤功能源自项目上交互优化用户体验,在表头添加过滤符号实现过滤,替换以往在表格上方占用一行过滤项进行过滤。
2. 过滤提示
过滤提示就是三态图标(normal,hover,press)。这三种状态的实现通过鼠标移动事件和鼠标点击事件来实现。具体实现如下:
1)hover状态在鼠标移动事件中实现
void CFilterHeaderView::mouseMoveEvent(QMouseEvent *e) { m_hover = logicalIndexAt(e->pos()); if (m_hover != -1) updateSection(m_hover); QHeaderView::mouseMoveEvent(e); } bool CFilterHeaderView::event(QEvent *e) { switch(e->type()) { case QEvent::Leave: case QEvent::HoverLeave: if (m_hover != -1) updateSection(m_hover); m_hover = -1; break; default: break; } return QHeaderView::event(e); }
如果悬浮在某一列上,hover值等于该列的index,否则等于-1。如果hover值不等于-1,则刷新该列(updateSection)。
mouseMoveEvent中检测鼠标悬浮在那个表格列上。event函数中监听Leave和HoverLeave事件。
2)press状态在鼠标点击事件中实现
void CFilterHeaderView::mousePressEvent(QMouseEvent *e) { m_press = logicalIndexAt(e->pos()); if (m_press != -1) updateSection(m_press); QHeaderView::mousePressEvent(e); } void CFilterHeaderView::mouseReleaseEvent(QMouseEvent *e) { m_press = -1; QHeaderView::mouseReleaseEvent(e); }
press的实现较为简单,鼠标点击更新press,鼠标释放press置为-1。
3)过滤提示的实现。
过滤提示在paintSection函数中实现,首先是调用基类paintSection实现表头的绘制,然后是检测有没有定义过滤角色。如果有定义过滤角色,则根据三态选择对应的图标,绘制位置默认水平靠右垂直居住,也可以自己指定位置。最后是绘制过滤提示。具体实现如下:
void CFilterHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const { painter->save(); QHeaderView::paintSection(painter, rect, logicalIndex); painter->restore(); QVariant filterVar = model()->headerData(logicalIndex, orientation(), FilterRole); if (filterVar.isValid() && filterVar.toBool()) { QPixmap pix = m_norFilterPix; bool b_contain = getFilterRect(rect).contains(cursor().pos()); if (logicalIndex == m_hover && b_contain) { pix = m_hovFilterPix; } if (logicalIndex == m_press && b_contain) { pix = m_preFilterPix; } int align = Qt::AlignRight | Qt::AlignVCenter; QVariant alignVar = model()->headerData(logicalIndex, orientation(), FilterAlignmentRole); if (alignVar.isValid()) { align = alignVar.toInt(); } style()->drawItemPixmap(painter, rect, align, pix); } }
表格绘制的区域和过滤提示绘制的区域不一致,要根据过滤图标大小进行计算过滤提示的区域。只有当鼠标在过滤区域位置上方,hover和press才有效,否则仍然是normal状态。过滤区域绘制的位置可以从外面获取,也可以使用默认位置。最后style()->drawItemPixmap进行绘制。
调用基类paintSection方法前后调用QPainter::save()和QPainter::restore()是必要的。如果不调用,style()->drawItemPixmap是不会起作用的。
4)过滤提示点击信号
点击过滤提示会发出信号,连接此信号可以进行过滤功能的实现。具体实现如下:
void CFilterHeaderView::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { int section = logicalIndexAt(e->pos()); QVariant filterVar = model()->headerData(section, orientation(), FilterRole); if (filterVar.isValid() && filterVar.toBool()) { QRect rect(sectionViewportPosition(section), 0, sectionSize(section), height()); if (getFilterRect(rect).contains(cursor().pos())) { emit filterClicked(section); } } } QHeaderView::mouseReleaseEvent(e); }
过滤信号发出的条件:1. 左键点击,2. 定义了过滤功能,3. 鼠标在过滤提示区域中
3. 使用过滤功能
使用过滤表头的方法如下:
m_tableView = new QTableView(this); m_model = new QStandardItemModel(this); m_filterModel = new QSortFilterProxyModel(this); m_filterModel->setSourceModel(m_model); m_filterModel->setSortRole(Qt::ToolTipRole); m_tableView->setModel(m_filterModel); QHBoxLayout* mainLayout = new QHBoxLayout(this); mainLayout->setMargin(0); mainLayout->addWidget(m_tableView); setLayout(mainLayout); m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_tableView->setSelectionMode(QAbstractItemView::SingleSelection); m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows); m_tableView->verticalHeader()->hide(); CFilterHeaderView* pHeader = new CFilterHeaderView(this); connect(pHeader, &CFilterHeaderView::filterClicked, this, &Widget::onFilterClicked); m_tableView->setHorizontalHeader(pHeader);
使用过滤表头和使用普通表头没有太大的差别。这里过滤功能有QSortFilterProxyModel实现,水平表头替换成自定义的CFilterHeaderView。
4. 写在最后
实现过滤表头的原理如上所诉。具体完整的项目路径参考如下地址:
https://github.com/zhugp125/QtDemo/tree/master/FilterHeaderView
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。
您可能感兴趣的文章:
- [Qt]自定义表头实现过滤功能
- VUE 自定义表头实现table的过滤功能
- 使用JQuery库提供的扩展功能实现自定义方法
- yii2高级应用之自定义组件实现全局使用图片上传功能的方法
- js对象如何实现数组索引功能并且自定义自己的方法 (4种方法)
- Java编程之TreeSet排序两种解决方法(1)元素自身具备比较功能,元素需要实现Comparable接口覆盖compare(2)创建根据自定义Person类的name进行排序的Comparator
- ASP.NET MVC 自定义过滤属性实现Enterprise的log功能
- Delphi中ListView中实现自定义删除功能的方法
- Java使用DFA算法实现过滤多家公司自定义敏感字功能详解
- Android编程实现自定义ImageView圆图功能的方法
- Android自定义搜索框(EditText)的搜索功能实现,过滤ListView
- 【Qt】自定义标题栏并实现最小化/最大化/关闭窗口功能
- 自定义商品数据,实现对商品的过滤、排序和删除功能
- Python自定义一个类实现字典dict功能的方法
- PHPCMS V9 自定义列表分页功能实现方法
- 自定义过滤条件的实现方法(1)
- 利用特性给方法实现自定义的功能
- Django 中自定义 Admin 样式与功能的实现方法
- 简单方法实现 uitableviewcell 左滑出现各种自定义功能视图
- JavaScript自定义方法实现trim()、Ltrim()、Rtrim()的功能