Qt自定義表頭實現(xiàn)過濾功能的方法
1. 寫在前面
過濾功能源自項目上交互優(yōu)化用戶體驗,在表頭添加過濾符號實現(xiàn)過濾,替換以往在表格上方占用一行過濾項進行過濾。
2. 過濾提示
過濾提示就是三態(tài)圖標(normal,hover,press)。這三種狀態(tài)的實現(xiàn)通過鼠標移動事件和鼠標點擊事件來實現(xiàn)。具體實現(xiàn)如下:
1)hover狀態(tài)在鼠標移動事件中實現(xiàn)
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函數(shù)中監(jiān)聽Leave和HoverLeave事件。
2)press狀態(tài)在鼠標點擊事件中實現(xiàn)
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的實現(xiàn)較為簡單,鼠標點擊更新press,鼠標釋放press置為-1。
3)過濾提示的實現(xiàn)。
過濾提示在paintSection函數(shù)中實現(xiàn),首先是調用基類paintSection實現(xiàn)表頭的繪制,然后是檢測有沒有定義過濾角色。如果有定義過濾角色,則根據(jù)三態(tài)選擇對應的圖標,繪制位置默認水平靠右垂直居住,也可以自己指定位置。最后是繪制過濾提示。具體實現(xiàn)如下:
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);
}
}
表格繪制的區(qū)域和過濾提示繪制的區(qū)域不一致,要根據(jù)過濾圖標大小進行計算過濾提示的區(qū)域。只有當鼠標在過濾區(qū)域位置上方,hover和press才有效,否則仍然是normal狀態(tài)。過濾區(qū)域繪制的位置可以從外面獲取,也可以使用默認位置。最后style()->drawItemPixmap進行繪制。
調用基類paintSection方法前后調用QPainter::save()和QPainter::restore()是必要的。如果不調用,style()->drawItemPixmap是不會起作用的。
4)過濾提示點擊信號
點擊過濾提示會發(fā)出信號,連接此信號可以進行過濾功能的實現(xiàn)。具體實現(xiàn)如下:
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);
}
過濾信號發(fā)出的條件:1. 左鍵點擊,2. 定義了過濾功能,3. 鼠標在過濾提示區(qū)域中
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實現(xiàn),水平表頭替換成自定義的CFilterHeaderView。
4. 寫在最后
實現(xiàn)過濾表頭的原理如上所訴。具體完整的項目路徑參考如下地址:
https://github.com/zhugp125/QtDemo/tree/master/FilterHeaderView
好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對我們的支持。
您可能感興趣的文章
- 01-10數(shù)據(jù)結構課程設計-用棧實現(xiàn)表達式求值的方法詳解
- 01-10使用OpenGL實現(xiàn)3D立體顯示的程序代碼
- 01-10求斐波那契(Fibonacci)數(shù)列通項的七種實現(xiàn)方法
- 01-10C語言 解決不用+、-、×、÷數(shù)字運算符做加法
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10用C++實現(xiàn)DBSCAN聚類算法
- 01-10深入全排列算法及其實現(xiàn)方法
- 01-10全排列算法的非遞歸實現(xiàn)與遞歸實現(xiàn)的方法(C++)
- 01-10用C語言實現(xiàn)單鏈表的各種操作(一)
- 01-10用C語言實現(xiàn)單鏈表的各種操作(二)


閱讀排行
本欄相關
- 04-02c語言函數(shù)調用后清空內存 c語言調用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調用函數(shù)求fibo C語言調用函數(shù)求
隨機閱讀
- 01-10C#中split用法實例總結
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10SublimeText編譯C開發(fā)環(huán)境設置
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 04-02jquery與jsp,用jquery
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改


