QRowTable表格控件(五)-重寫表頭排序、支持第三次單擊恢復默認排序

[TOC]html

原文連接:QRowTable表格控件(五)-重寫表頭排序、支持第三次單擊恢復默認排序程序員

1、原生表格

開發客戶端程序的方式愈來愈多了,如今很流行的libcef、electron等等均可以做爲快速開發客戶端軟件的方案,可是若是須要一個好的用戶體驗,仍是離不開原生化的開發,雖然慢,可是性能好啊。瀏覽器

說到原生化開發,那對應的UI庫相對較多,流行的就有Qt、soui、duilib、還有老掉牙的MFC和其餘一些第三方公司開源維護的directUI庫等等。網上找到一篇整理的文章,有興趣的同窗能夠參考C++界面庫框架

目前C++客戶端使用最普遍的就是UI框架就是Qt,它不只包含了GUI控件,更多的實際上是一種解決方案,使用過Qt的同窗都比較清楚,Qt的安裝動態庫有幾十個之多,但是若是你只想使用Qt的GUi模塊的話,就只須要包含3個動態庫便可,他們分別是核心模塊QtCore、Gui模塊QtGui和QtWidget。electron

當咱們將Qt做爲咱們的開發SDK時,大多數時候原生的控件+qss美化就能夠完成咱們的需求,然而總有一些特殊狀況,好比產品經理腦殘的時候、或者說是業務場景傻逼了,老是須要完成一些奇奇怪怪交互,那麼咱們就須要重寫原生的控件實現方式。函數

今天就來講一個案例--表格控件列排序方式。性能

對於某一些特殊的場景下,咱們的表格展現的數據可能須要排序,這樣的表格控件Qt已經給咱們提供好了,只須要咱們從寫一些類和接口便可。前邊已經寫了4篇關於表格控件的功能,分別是QRowTable表格控件-支持hover整行、checked整行、指定列排序等QRowTable表格控件(二)-紅漲綠跌QRowTable表格控件(三)-效率優化之-合理使用QStandardItemQRowTable表格控件(四)-效率優化之-優化數據源,感興趣的同窗能夠去看看。字體

不幸的是Qt自帶的表格排序功能,便是咱們衝寫完全部接口依然不能知足負責的業務需求--表格表頭連續3點三次是一個循環,什麼意思呢?優化

傳統表格排序ui

Qt自帶的表格排序行爲是這樣的,默認狀況是不排序的,咱們能夠經過接口開啓排序,或者經過接口設置不排序,當咱們啓用排序規則後,假設說咱們的表格點擊點擊一下是降序,點擊第二下就是升序,再次點擊是又會恢復到降序規則,這樣是否是還挺完美呢!

這個時候產品有話說了,點擊第三次時,須要設置程序爲不排序。

程序員:臥槽。。。。你說什麼。。。。聽不到。。。。

新的排序規則

在傳統表格排序的基礎上作一下調整

  1. 能夠支持某些列不容許排序
  2. 3次連續單擊爲一個循環,也就是降序-升序-無序這樣3個狀態循環

不得不說產品的腦洞仍是很大的。既然產品都說想要這個功能了,那麼有時間仍是得考慮下。跟產品溝通良久後,有了以下安排,雖然這個功能對用戶來講不是一個特別須要的功能,可是當咱們的軟件功能穩定後,迭代沒有那麼着急的時候,是否是能夠考慮研究下這個而功能呢。

而後也就有了本篇文章

雖然重寫了Qt自己的邏輯,沒想到仍是能夠實現的!!!

2、效果展現

按照慣例先上圖,看看是否是同窗們想要的功能。

<center> <img src="https://images.cnblogs.com/cnblogs_com/swarmbees/1497876/o_row_table_sort.gif" /> </center>

3、實現方式

新的表格排序有2個點須要咱們去思考,分別是某些列排序、排序交互修改,下面咱們分開來去實現

一、排序列定製

Qt默認提供了可排序接口,可是開啓後咱們全部的列都支持排序了,這個時候咱們就須要研究Qt的源碼,看看Qt的排序是怎麼觸發的,而後在合理的時機去加上咱們不支持排序的邏輯

博主這裏找到的作法是重寫QHaderView這個類,並重寫實現了鼠標按下並擡起的接口,在這個接口中判斷咱們業務層是否是容許排序。

重寫後的邏輯是這樣的

  1. 若是不容許排序,咱們先調用Qt原有的接口禁用全部列排序功能

  2. 調用父類的鼠標擡起函數

  3. 若是不容許排序,須要調用Qt原有的接口啓用全部列排序功能

以上邏輯的步驟2是原有的邏輯,步驟1和步驟3分別是在進行業務邏輯判斷後進行的邏輯調整,達到咱們禁用某些列排序的功能

void QRowHeader::mouseReleaseEvent(QMouseEvent * event)
{
	int column = logicalIndexAt(event->pos().x());
	if (m_Indicator.contains(column) 
		&& m_Indicator[column] == false
		&& qAbs(event->x() - m_pPressPos.x()) < QApplication::startDragDistance()/*非拖拽*/)
	{
		setSectionsClickable(false);
		QHeaderView::mouseReleaseEvent(event);
		setSectionsClickable(true);
	}
	
	QHeaderView::mouseReleaseEvent(event);
	...

如上代碼,m_Indicator結構中存儲了咱們想要定製的是否容許排序的列,只須要對外暴露一個修改接口便可,代碼是否是還很簡單呢。

void QRowHeader::SetSortEnable(int logicalIndex, bool enable)
{
	m_Indicator[logicalIndex] = enable;
}

這樣禁用某些列排序的功能就是實現了。

禁用某些列排序這個功能相對來講好實現一些,畢竟重寫的邏輯不是特別複雜,下面咱們來看下怎麼修改排序交互邏輯。

二、排序交互修改

有了前面的問題處理思路,這個功能依然如此,咱們先跟Qt源碼,看看已有的排序交互邏輯實現怎麼實現的,而後在合理的實際去重置某些變量的值,達到重寫交互邏輯。

博主這裏跟蹤完Qt默認的排序實現方式後,發現重寫這個功能仍是有必定難度的,首先數據排序是一塊,另外一塊是一旦啓用排序後,排序箭頭的繪製這塊也須要去重寫。

什麼意思呢?

Qt的排序規則一旦啓用,排序的箭頭就會被繪製,而且繪製箭頭的邏輯還簡單粗暴,不是升序就是降序。

且看以下Qt表頭繪製源碼

若是顯示排序箭頭而且是排序列,則須要繪製排序箭頭,不是降序就是升序

我:我槽。。。什麼鬼,就不能提供一個空的枚舉嗎?

void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
    ...
    if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex)
        opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
                            ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
    ...
}

既然這條路子是走不通了,那麼咱們只能取巧,換其餘方式。

終於、皇天不負有心人被博主想到一個好辦法,代碼量依然仍是不多。

回到咱們最開始的需求,咱們其實就是想讓第三次點擊時,只是一個特殊的操做,而後把第四點擊當作第一次單擊便可。

有了這個想法後,那麼就來幹吧,既然仍是重寫鼠標擡起函數,想盡一切辦法監控連續的第三次單擊,把他處理成非排序狀態,而後在下一次單擊時,走正常的排序邏輯。

void QRowHeader::mouseReleaseEvent(QMouseEvent * event)
{
    ...
    QHeaderView::mouseReleaseEvent(event);

	column = logicalIndexAt(event->pos().x());
	static bool nextNoSort = false;
	static int prevColumn = -1;
	if (nextNoSort && prevColumn == column
		&& qAbs(event->x() - m_pPressPos.x()) < QApplication::startDragDistance())
	{
		emit RestoreSort();//恢復默認排序
	}

	if (nextNoSort != true
		&& prevColumn == column
		&& sectionsClickable()
		&& sortIndicatorOrder() == Qt::DescendingOrder)
	{
		if (qAbs(event->x() - m_pPressPos.x()) < QApplication::startDragDistance())
		{
			nextNoSort = true;
			prevColumn = column;
		}
		else
		{
			nextNoSort = false;
		}
	}
	else
	{
		if (nextNoSort && qAbs(event->x() - m_pPressPos.x()) >= QApplication::startDragDistance())
		{
			nextNoSort = true;
		}
		else
		{
			nextNoSort = false;
			prevColumn = column;
		}
	}
	...
}

好了,代碼以上。不過這裏重點仍是要說下爲何這麼幹!

首先須要調用父類的mouseReleaseEvent函數,不然拖拽會有問題,並且必須調用這個函數纔可讓內存數據正常。

而後咱們記錄了一系列內存狀態,判斷是否是須要恢復排序狀態,當條件知足時發出RestoreSort信號,外部程序只須要接收這個信號,而後恢復默認排序便可。

恢復默認排序

void QRowTable::RestoreSort()
{
	m_pFilter->SetCompareType(QFilterModel::CT_NULL);
	m_pFilter->invalidate();
	m_pHHeader->setSortIndicator(-1, Qt::DescendingOrder);
}

4、相關文章

  1. Qt實現表格控件-支持多級列表頭、多級行表頭、單元格合併、字體設置等

  2. Qt高仿Excel表格組件-支持凍結列、凍結行、內容自適應和合並單元格

  3. 屬性瀏覽器控件QtTreePropertyBrowser編譯成動態庫(設計師插件)

  4. 超級實用的屬性瀏覽器控件--QtTreePropertyBrowser

  5. Qt之表格控件螞蟻線

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

  7. QRowTable表格控件(二)-紅漲綠跌

  8. QRowTable表格控件(三)-效率優化之-合理使用QStandardItem

  9. QRowTable表格控件(四)-效率優化之-優化數據源

  10. C++界面庫


值得一看的優秀文章:

  1. 財聯社-產品展現
  2. 廣聯達-產品展現
  3. Qt定製控件列表
  4. 牛逼哄哄的Qt庫

<br> <html> <div style='font-weight:600;'> 若是您以爲文章不錯,不妨給個<span style='font-size:24px;color:blue;'>打賞</span>,寫做不易,感謝各位的支持。您的支持是我最大的動力,謝謝!!! </div> <center> <div> <table> <tr> <td><img src=https://www.cnblogs.com/images/cnblogs_com/swarmbees/1497876/o_weixin_reward.png border=0></td> <td><img src=https://www.cnblogs.com/images/cnblogs_com/swarmbees/1497876/o_zhifubao_reward.png border=0></td> </tr> </table> </div> </center> </html>

<br><br>


很重要--轉載聲明

  1. 本站文章無特別說明,皆爲原創,版權全部,轉載時請用連接的方式,給出原文出處。同時寫上原做者:朝十晚八 or Twowords

  2. 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時經過修改本文達到有利於轉載者的目的。


原文出處:https://www.cnblogs.com/swarmbees/p/11519796.html

相關文章
相關標籤/搜索