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. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时经过修改本文达到有利于转载者的目的。 

相关文章
相关标签/搜索