Qt中怎么通过自定义表头实现过滤功能,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
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。
关于Qt中怎么通过自定义表头实现过滤功能问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。