Qt之表格控件螞蟻線

1、螞蟻線

  摘自互動百科:在圖像影像軟件中表示選區的動態虛線,由於虛線閃爍的樣子像是一羣螞蟻在跑,因此俗稱螞蟻線。在Poshop,After Effect等軟件中比較常見。app

  背景:用過excel的同窗都知道,當對單元格進行復制時,單元格周圍就會出現一個跑動的矩形框,這個矩形框就被稱爲螞蟻線。經過設置螞蟻線的線型和調整控件有效刷新次數咱們能夠獲得不一樣的跑動效果,這是一個很是有意思的現象。函數

2、效果展現

  以下圖就是螞蟻線的效果截圖,單擊單元格時,會繪製一個2個像素寬的外框;當雙擊某個單元格時,就會產生螞蟻線,螞蟻線的線型和跑動速度均可以定製。文末會放出演示代碼下載連接。post

3、實現

  說到Qt繪圖,確定離不開paintEvent函數,並且大多數的功能均可以經過重寫paintEvent函數來完成。凡是總有例外,當控件自己就比較複雜,或者只須要重寫控件某一部分時,就須要重寫一些其餘東西來完成需求,好比表格螞蟻線繪製就屬於這個例外,當咱們重寫表格時就不能重寫paintEvent函數,若是重寫這個函數那麼表格的全部東西就須要咱們本身去繪製,一個好的辦法就是重寫 QStyledItemDelegate代理類,經過這個類咱們能夠定製表格控件的每個項。下面咱們就來仔細的分析下基於重寫代理類的實現細節,理解下面4個實現維度後螞蟻線基本就完成了。
一、繪製區域
  螞蟻線是針對表格項來進行繪製的,所以首先想到的就是刷新表格某一項來進行提升繪製效率,經過閱讀Qt源碼,找到QTableView::paintEvent函數中對錶格項進行了繪製,主要是經過調用QTableViewPrivate::drawCell函數來進行每一個單元格的繪製,該函數最後一行是經過QStyledItemDelegate類的paint方法來進行繪製,與第三節第一段的說明對應起來。所以若是想進行局部刷新看來困難比較大,所以最終決定每次刷新螞蟻線時對整個表格進行刷新。
二、定時器
  定時刷新,顧名思義就是咱們須要一個定時器,定時刷新表格控件。首先想到的是咱們本身維護一個QTimer,經過QTimer::timeout信號來刷新表格;除此以外QObject類已經幫咱們提供了一個timerEvent回調函數,咱們只須要經過startTime接口來啓動一個定時器,timerEvent函數就會被定時調用,固然了這個回調接口同時支持多個定時器,用timeID進行區分每一個定時器。
三、繪製策略
  當選擇一個單元格時(當前單元格發現變化),繪製矩形框;繪製矩形框比較簡單,這塊須要注意一個地方,就是當繪製第一列的時候矩形框可能會跑出當前項,致使矩形框顯示不全。螞蟻線繪製時也存在這個問題。
void GMPFileItemDelegate::DrawBorderRect( QPainter * painter, const QRect & rect, bool firstColumn ) const
{
	painter->save();
	QPen pen = painter->pen();
	pen.setWidth(2);
	pen.setColor(QColor(0, 132, 255));
	painter->setPen(pen);

	QRect tmpRect = rect; 
	if (firstColumn)
	{
		tmpRect.adjust(2, 1, -1, -1);
	}
	else
	{
		tmpRect.adjust(1, 1, -1, -1);
	}
	painter->drawRect(tmpRect);
	painter->restore();
}
  當雙擊單元格時繪製螞蟻線, 螞蟻線繪製是經過定時器進行控制線框奔跑速度,這塊有一個須要注意的地方是隻有當定時器引發的繪製纔會使螞蟻線往前跑。
根據螞蟻線的偏移繪製開始的空白區域,螞蟻線是由7個像素的藍色和2個像素的空白循環組成,當偏移10個像素時,從新回到偏移1個像素。
if (startPoint != truthPoint && offset > 2)
{
	QPolygon polygon;
	for (int i = 4; i <= offset; ++i)//繪製前邊偏移的像素
	{
		if (polygon.size() >= 7)
		{
			break;
		}
		polygon.append(truthPoint - QPoint(i , 0));
	}
	painter->drawPoints(polygon);
}
四、界面刷新
  qt有本身的界面刷新策略,平時使用比較多的也不外乎update(建議刷新)、repaint(強制刷新)兩個接口,可是這個兩個接口調用時也不是說界面確定會刷新,其實這兩個接口都是使用 QWidgetBackingStoreTracker類的sendUpdateRequest接口類來拋出的界面刷新事件,Qt窗口有一個dirtyWidget的概念,當斷定這個窗口爲須要刷新的窗口時纔會調用sendUpdateRequest接口進行界面刷新,以下代碼,update和repaint區別在於調用了switch的不一樣分支。
void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTime)
{
    if (!widget)
        return;

    switch (updateTime) {
    case UpdateLater:
        updateRequestSent = true;
        QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
        break;
    case UpdateNow: {
        QEvent event(QEvent::UpdateRequest);
        QApplication::sendEvent(widget, &event);
        break;
        }
    }
}
  對於表格控件當咱們單純調用repaint或者update函數時是不能起到刷新界面的做用,所以咱們須要調用其餘能直接致使界面刷新的接口,目前我這塊想到了直接 調用窗口自身style的polish方法,若是你們有其餘好的刷新方式能夠留言。
經過以上4個小點的說明,螞蟻線的實現基本就完成了。須要完整源碼的去csdn下載吧

4、下載連接

  Qt螞蟻線-表格spa

若是您以爲文章不錯,不妨給個打賞,寫做不易,感謝各位的支持。您的支持是我最大的動力,謝謝!!! 

 

  


很重要--轉載聲明.net

  1. 本站文章無特別說明,皆爲原創,版權全部,轉載時請用連接的方式,給出原文出處。同時寫上原做者:朝十晚八 or Twowords
  2. 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時經過修改本文達到有利於轉載者的目的。 

相關文章
相關標籤/搜索