一、蚂蚁线

  摘自互动百科:在图像影像软件中表示选区的动态虚线,因为虚线闪烁的样子像是一群蚂蚁在跑,所以俗称蚂蚁线。在Poshop,After Effect等软件中比较常见。

  背景:用过excel的同学都知道,当对单元格进行复制时,单元格周围就会出现一个跑动的矩形框,这个矩形框就被称为蚂蚁线。通过设置蚂蚁线的线型和调整控件有效刷新次数我们可以得到不同的跑动效果,这是一个非常有意思的现象。

二、效果展示

  如下图就是蚂蚁线的效果截图,单击单元格时,会绘制一个2个像素宽的外框;当双击某个单元格时,就会产生蚂蚁线,蚂蚁线的线型和跑动速度都可以定制。文末会放出演示代码下载链接。

三、实现

  说到Qt绘图,肯定离不开paintEvent函数,而且大多数的功能都可以通过重写paintEvent函数来完成。凡是总有例外,当控件本身就比较复杂,或者只需要重写控件某一部分时,就需要重写一些其他东西来完成需求,比如表格蚂蚁线绘制就属于这个例外,当我们重写表格时就不能重写paintEvent函数,如果重写这个函数那么表格的所有东西就需要我们自己去绘制,一个好的办法就是重写QStyledItemDelegate代理类,通过这个类我们可以定制表格控件的每一个项。下面我们就来仔细的分析下基于重写代理类的实现细节,理解下面4个实现维度后蚂蚁线基本就完成了。
1、绘制区域
  蚂蚁线是针对表格项来进行绘制的,因此首先想到的就是刷新表格某一项来进行提高绘制效率,通过阅读Qt源码,找到QTableView::paintEvent函数中对表格项进行了绘制,主要是通过调用QTableViewPrivate::drawCell函数来进行每个单元格的绘制,该函数最后一行是通过QStyledItemDelegate类的paint方法来进行绘制,与第三节第一段的说明对应起来。因此如果想进行局部刷新看来困难比较大,因此最终决定每次刷新蚂蚁线时对整个表格进行刷新。
2、定时器
  定时刷新,顾名思义就是我们需要一个定时器,定时刷新表格控件。首先想到的是我们自己维护一个QTimer,通过QTimer::timeout信号来刷新表格;除此之外QObject类已经帮我们提供了一个timerEvent回调函数,我们只需要通过startTime接口来启动一个定时器,timerEvent函数就会被定时调用,当然了这个回调接口同时支持多个定时器,用timeID进行区分每个定时器。
3、绘制策略
  当选择一个单元格时(当前单元格发现变化),绘制矩形框;绘制矩形框比较简单,这块需要注意一个地方,就是当绘制第一列的时候矩形框可能会跑出当前项,导致矩形框显示不全。蚂蚁线绘制时也存在这个问题。
  1. void GMPFileItemDelegate::DrawBorderRect( QPainter * painter, const QRect & rect, bool firstColumn ) const
  2. {
  3. painter->save();
  4. QPen pen = painter->pen();
  5. pen.setWidth(2);
  6. pen.setColor(QColor(0, 132, 255));
  7. painter->setPen(pen);
  8.  
  9. QRect tmpRect = rect;
  10. if (firstColumn)
  11. {
  12. tmpRect.adjust(2, 1, -1, -1);
  13. }
  14. else
  15. {
  16. tmpRect.adjust(1, 1, -1, -1);
  17. }
  18. painter->drawRect(tmpRect);
  19. painter->restore();
  20. }
  当双击单元格时绘制蚂蚁线,蚂蚁线绘制是通过定时器进行控制线框奔跑速度,这块有一个需要注意的地方是只有当定时器引起的绘制才会使蚂蚁线往前跑。
根据蚂蚁线的偏移绘制开始的空白区域,蚂蚁线是由7个像素的蓝色和2个像素的空白循环组成,当偏移10个像素时,重新回到偏移1个像素。
  1. if (startPoint != truthPoint && offset > 2)
  2. {
  3. QPolygon polygon;
  4. for (int i = 4; i <= offset; ++i)//绘制前边偏移的像素
  5. {
  6. if (polygon.size() >= 7)
  7. {
  8. break;
  9. }
  10. polygon.append(truthPoint - QPoint(i , 0));
  11. }
  12. painter->drawPoints(polygon);
  13. }
4、界面刷新
  qt有自己的界面刷新策略,平时使用比较多的也不外乎update(建议刷新)、repaint(强制刷新)两个接口,但是这个两个接口调用时也不是说界面肯定会刷新,其实这两个接口都是使用QWidgetBackingStoreTracker类的sendUpdateRequest接口类来抛出的界面刷新事件,Qt窗口有一个dirtyWidget的概念,当判定这个窗口为需要刷新的窗口时才会调用sendUpdateRequest接口进行界面刷新,如下代码,update和repaint区别在于调用了switch的不同分支。
  1. void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTime)
  2. {
  3. if (!widget)
  4. return;
  5.  
  6. switch (updateTime) {
  7. case UpdateLater:
  8. updateRequestSent = true;
  9. QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
  10. break;
  11. case UpdateNow: {
  12. QEvent event(QEvent::UpdateRequest);
  13. QApplication::sendEvent(widget, &event);
  14. break;
  15. }
  16. }
  17. }
  对于表格控件当我们单纯调用repaint或者update函数时是不能起到刷新界面的作用,因此我们需要调用其他能直接导致界面刷新的接口,目前我这块想到了直接调用窗口自身style的polish方法,如果大家有其他好的刷新方式可以留言。
通过以上4个小点的说明,蚂蚁线的实现基本就完成了。需要完整源码的去csdn下载吧

四、下载链接

  Qt蚂蚁线-表格

如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!! 

 

很重要--转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords
  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。

Qt之表格控件蚂蚁线的更多相关文章

  1. Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等

    目录 一.概述 二.效果展示 三.定制表头 1.重写数据源 2.重写QHeaderView 四.设置属性 五.相关文章 原文链接:Qt实现表格控件-支持多级列表头.多级行表头.单元格合并.字体设置等 ...

  2. qt tableWidget 表格控件使用

    //创建表格头 (灰色冻结状态的) QStringList header; header<<"Time"<<" ID "<< ...

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

    目录 一.开心一刻 二.嘴一嘴 三.效果展示 四.浅谈实现 五.自定义数据源 1.data函数 2.flags函数 六.自定义视图 1.目的 2.问题分析 七.测试 八.相关文章 原文链接:QRowT ...

  4. QRowTable表格控件(二)-红涨绿跌

    目录 一.开心一刻 二.概述 三.效果展示 四.任务需求 五.指定列排序 六.排序 七.列对其方式 八.相关文章 原文链接:QRowTable表格控件(二)-红涨绿跌 一.开心一刻 一天,五娃和六娃去 ...

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

    目录 一.开心一刻 二.概述 三.效果展示 四.QStandardItem 1.QStandardItem是什么鬼 2.性能分析 3.QStandardItem使用上的坑 五.相关文章 原文链接:QR ...

  6. QTableView表格控件区域选择-自绘选择区域

    目录 一.开心一刻 二.概述 三.效果展示 四.实现思路 1.绘制区域 2.绘制边框 3.绘制 五.相关文章 原文链接:QTableView表格控件区域选择-自绘选择区域 一.开心一刻 陪完客户回到家 ...

  7. QRowTable表格控件(四)-效率优化之-优化数据源

    目录 一.开心一刻 二.问题分析 三.重写数据源 1.自己存储数据 2.重写data接口 四.比较 五.相关文章 原文链接:QRowTable表格控件(四)-效率优化之-优化数据源 一.开心一刻 一程 ...

  8. QRowTable表格控件(五)-重写表头排序、支持第三次单击恢复默认排序

    目录 一.原生表格 二.效果展示 三.实现方式 1.排序列定制 2.排序交互修改 四.相关文章 原文链接:QRowTable表格控件(五)-重写表头排序.支持第三次单击恢复默认排序 一.原生表格 开发 ...

  9. [ PyQt入门教程 ] PyQt5中数据表格控件QTableWidget使用方法

    如果你想让你开发的PyQt5工具展示的数据显得整齐.美观.好看,显得符合你的气质,可以考虑使用QTableWidget控件.之前一直使用的是textBrowser文本框控件,数据展示还是不太美观.其中 ...

随机推荐

  1. EF Code First中的主外键约定和一对一、一对多关系的实现

    对于主外键约定的理解,其实是学习实体间一对一和一对多关系的基础. 1.1 主键(Key)约定 主键的默认约定是:只要字段名为--实体名(类名)+"id"(不区分大小写),这就算是默 ...

  2. Learn flask in the hard way:配置环境的安装

    开发用的是win10的环境. 首先确保安装了python环境,个人比较适应python2.x的代码方式,所以安装的是python2.7.10. 另外IDE还是我最喜欢的pycharm. 然后开始安装F ...

  3. SpringBoot Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback.

    使用SpringBoot写HelloWorld,当配置好启动类后,再创建新的controller或其它类,启动项目后访问对应的映射名,页面显示: Whitelabel Error Page This ...

  4. mapreduce shuffle 和sort 详解

        MapReduce 框架的核心步骤主要分两部分:Map 和Reduce.当你向MapReduce 框架提交一个计算作业时,它会首先把计算作业拆分成若干个Map 任务,然后分配到不同的节点上去执 ...

  5. Android 开发TCP协议时,报错NetworkOnMainThreadException

    设想是通过Android应用连接PC的TCP服务器,通过点击按钮连接服务器, 最终在点击按钮后报错:networkonmainthreadexception 解决办法: 在MainActivity文件 ...

  6. SpringMVC中利用@CrossOrigin注解解决ajax跨域请求的问题

    1. 什么是跨域 跨域,即跨站HTTP请求(Cross-site HTTP request),指发起请求的资源所在域不同于请求指向资源所在域的HTTP请求. 2. 跨域的应用情景 当使用前后端分离,后 ...

  7. java 23种设计模式教程

    设计模式分类 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. 行为型模 ...

  8. 数据结构 之 并查集(Disjoint Set)

    一.并查集的概念:     首先,为了引出并查集,先介绍几个概念:     1.等价关系(Equivalent Relation)     自反性.对称性.传递性.     如果a和b存在等价关系,记 ...

  9. 使用box-shadow进行画图(性能优化终结者)

    最近突然想做一些好玩的东西,找来找去,想到了之前曾经在网上看到过有人用box-shadow画了一副蒙娜丽莎出来感觉这个挺有意思,正好趁着周末,自己也搞一波 前言 在线地址: 优化前的版本优化后的版本源 ...

  10. 让站点支持MarkDown语法~(转)

    Markdown是一种可以使用普通文本编辑器编写的标记语言,通过类似HTML的标记语法,它可以使普通文本内容具有一定的格式.Markdown的语法简洁明了.学习容易,而且功能比纯文本更强,因此有很多人 ...