一、前言

垂直时间轴控件,主要用来描述企业发展历程大事件,或者软件版本迭代历史等,通过时间节点和事件描述来直观的展示发展的过程,一般在web网页或者app中经常看到此类控件,尤其是公司的官网关于公司部分,着重在一些独角兽公司或者正处于蓬勃发展的公司,用来展示自己多牛逼,发展多么迅猛等。

垂直时间轴控件主要存储的数据包含两个,一个是时间节点,一个是事件描述,为了后期的拓展性,采用结构体来存放这个数据,比如后期还可能增加该事件是否属于重大事件标记,是的话则绘制的时候突出显示比如加大字号加粗,本控件的主要难点在于自动计算和排列来绘制时间和事件描述,默认采用对等分的机制来处理绘制,还有部分时间轴控件是左侧时间右侧事件描述,这个可以在源码基础上自行更改或者增加样式,为了能够展示所有的事件,本控件主体是继承自滚动条区域控件,超过高度自动产生滚动条。

二、实现的功能

  • 1:可设置节点边距
  • 2:可设置节点高度
  • 3:可设置信息边框边距
  • 4:可设置信息所占高度
  • 5:可设置基准颜色/线条颜色
  • 6:可设置标题/信息集合
  • 7:自动产生滚动条
  • 8:支持字符串形式设置数据

三、效果图



四、头文件代码

#ifndef TIMEAXIS_H
#define TIMEAXIS_H /**
* 垂直时间轴控件 作者:雨田哥(QQ:3246214072) 整理:feiyangqingyun(QQ:517216493) 2019-10-07
* 1:可设置节点边距
* 2:可设置节点高度
* 3:可设置信息边框边距
* 4:可设置信息所占高度
* 5:可设置基准颜色/线条颜色
* 6:可设置标题/信息集合
* 7:自动产生滚动条
* 8:支持字符串形式设置数据
*/ #include <QScrollArea>
class TimeAxisWidget; #ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif class QDESIGNER_WIDGET_EXPORT TimeAxis : public QScrollArea
#else
class TimeAxis : public QScrollArea
#endif {
Q_OBJECT
Q_PROPERTY(int itemMargin READ getItemMargin WRITE setItemMargin)
Q_PROPERTY(int itemHeight READ getItemHeight WRITE setItemHeight)
Q_PROPERTY(int infoPadding READ getInfoPadding WRITE setInfoPadding)
Q_PROPERTY(int infoHeight READ getInfoHeight WRITE setInfoHeight) Q_PROPERTY(QColor baseColor READ getBaseColor WRITE setBaseColor)
Q_PROPERTY(QColor lineColor READ getLineColor WRITE setLineColor) Q_PROPERTY(QString title READ getTitle WRITE setTitle)
Q_PROPERTY(QString infos READ getInfos WRITE setInfos) public:
explicit TimeAxis(QWidget *parent = 0); private:
int itemMargin; //节点边距
int itemHeight; //节点高度
int infoPadding; //信息边距
int infoHeight; //信息高度 QColor baseColor; //基准颜色
QColor lineColor; //线条颜色 QString title; //标题
QString infos; //信息集合 //时间轴主控件
TimeAxisWidget *timeAxisWidget; public:
int getItemMargin() const;
int getItemHeight() const;
int getInfoPadding() const;
int getInfoHeight() const; QColor getBaseColor() const;
QColor getLineColor() const; QString getTitle() const;
QString getInfos() const; QSize sizeHint() const;
QSize minimumSizeHint() const; TimeAxisWidget *getWidget(); public Q_SLOTS:
//设置节点边距+节点高度
void setItemMargin(int itemMargin);
void setItemHeight(int itemHeight); //设置信息边距+信息高度
void setInfoPadding(int infoPadding);
void setInfoHeight(int infoHeight); //设置基准颜色+线条颜色
void setBaseColor(const QColor &baseColor);
void setLineColor(const QColor &lineColor); //设置标题+信息集合
void setTitle(const QString &title);
void setInfos(const QString &infos);
}; class TimeAxisWidget : public QWidget
{
Q_OBJECT public:
//可以自行拓展其他信息
struct TimeAxisInfo {
QString time; //时间
QString info; //信息
}; explicit TimeAxisWidget(QWidget *parent = 0); protected:
void paintEvent(QPaintEvent *);
void drawTitle(QPainter *painter);
void drawLine(QPainter *painter);
void drawInfo(QPainter *painter);
void drawInfoRight(QPainter *painter, const QRectF &infoRect, int infoHeight);
void drawInfoLeft(QPainter *painter, const QRectF &infoRect, int infoHeight); private:
int itemMargin; //节点边距
int itemHeight; //节点高度
int infoPadding; //信息边距
int infoHeight; //信息高度 QColor baseColor; //基准颜色
QColor lineColor; //线条颜色 QString title; //标题
QString infos; //信息集合 //信息集合结构体
QList<TimeAxisInfo> itemInfos; public:
int getItemMargin() const;
int getItemHeight() const;
int getInfoPadding() const;
int getInfoHeight() const; QColor getBaseColor() const;
QColor getLineColor() const; QString getTitle() const;
QString getInfos() const; QSize sizeHint() const;
QSize minimumSizeHint() const; public Q_SLOTS:
//设置节点边距+节点高度
void setItemMargin(int itemMargin);
void setItemHeight(int itemHeight); //设置信息边距+信息高度
void setInfoPadding(int infoPadding);
void setInfoHeight(int infoHeight); //设置基准颜色+线条颜色
void setBaseColor(const QColor &baseColor);
void setLineColor(const QColor &lineColor); //设置标题+信息集合
void setTitle(const QString &title);
void setInfos(const QString &infos); //设置信息集合,结构体方式
void setItemInfos(const QList<TimeAxisInfo> &itemInfos);
}; #endif // TIMEAXIS_H

五、核心代码

void TimeAxisWidget::drawTitle(QPainter *painter)
{
painter->save(); QFont font;
font.setBold(true);
font.setPointSize(16);
painter->setFont(font); painter->setPen(baseColor);
painter->drawText(itemMargin, itemMargin, width() - 2 * itemMargin, 40, Qt::AlignCenter, title); painter->restore();
} void TimeAxisWidget::drawLine(QPainter *painter)
{
painter->save();
painter->setPen(QPen(lineColor, 6));
int startY = itemMargin + 50;
int endY = startY + itemInfos.size() * itemHeight;
painter->drawLine(width() / 2.0, startY, width() / 2.0, endY);
painter->restore(); //设置下固定高度
this->setFixedHeight(endY + itemMargin);
} void TimeAxisWidget::drawInfo(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen); QFont font;
font.setPointSize(12);
painter->setFont(font); int startY = itemMargin + 50;
int centerX = this->width() / 2.0;
int spacer = itemMargin + 10; //追个绘制时间轴信息集合,偶数行左侧绘制时间右侧绘制信息
for (int i = 0; i < itemInfos.size(); i++) {
painter->setBrush(Qt::white);
painter->setPen(QPen(baseColor, 2)); if (i % 2 == 0) {
//绘制时间
QRectF textRect(0, startY, centerX - spacer, itemHeight);
painter->drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, itemInfos.at(i).time);
//绘制信息边框
QRectF infoRect(centerX + spacer, textRect.center().y() - infoHeight / 2.0, centerX - spacer - itemMargin - infoHeight / 2.0, infoHeight);
drawInfoRight(painter, infoRect, infoHeight);
//绘制信息背景
painter->setBrush(baseColor);
drawInfoRight(painter, infoRect.adjusted(infoPadding, infoPadding, 0, -infoPadding), infoHeight - infoPadding * 2);
//绘制信息文字
painter->setPen(Qt::white);
painter->drawText(infoRect.adjusted(infoPadding, infoPadding, 0, -infoPadding), Qt::AlignCenter, itemInfos.at(i).info);
} else {
//绘制时间
QRectF textRect(centerX + spacer, startY, centerX - spacer, itemHeight);
painter->drawText(centerX + spacer, startY, centerX - spacer, itemHeight, Qt::AlignLeft | Qt::AlignVCenter, itemInfos.at(i).time);
//绘制信息边框
QRectF infoRect(itemMargin + infoHeight / 2.0, textRect.center().y() - infoHeight / 2.0, centerX - spacer - itemMargin - infoHeight / 2.0, infoHeight);
drawInfoLeft(painter, infoRect, infoHeight);
//绘制信息背景
painter->setBrush(baseColor);
drawInfoLeft(painter, infoRect.adjusted(0, infoPadding, -infoPadding, -infoPadding), infoHeight - infoPadding * 2);
//绘制信息文字
painter->setPen(Qt::white);
painter->drawText(infoRect.adjusted(0, infoPadding, -infoPadding, -infoPadding), Qt::AlignCenter, itemInfos.at(i).info);
} //绘制垂直线对应的圆
painter->setPen(Qt::NoPen);
painter->setBrush(baseColor);
painter->drawEllipse(centerX - 8, startY + itemHeight / 2.0 - 8, 16, 16);
painter->setBrush(Qt::white);
painter->drawEllipse(centerX - 4, startY + itemHeight / 2.0 - 4, 8, 8); //Y轴往下移一个高度
startY += itemHeight;
} painter->restore();
}

六、控件介绍

  1. 超过160个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。
  2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。
  3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.13的任何Qt版本,支持mingw、msvc、gcc等编译器,支持任意操作系统比如windows+linux+mac+嵌入式linux等,不乱码,可直接集成到Qt Creator中,和自带的控件一样使用,大部分效果只要设置几个属性即可,极为方便。
  4. 每个控件都有一个对应的单独的包含该控件源码的DEMO,方便参考使用。同时还提供一个所有控件使用的集成的DEMO。
  5. 每个控件的源代码都有详细中文注释,都按照统一设计规范编写,方便学习自定义控件的编写。
  6. 每个控件默认配色和demo对应的配色都非常精美。
  7. 超过130个可见控件,6个不可见控件。
  8. 部分控件提供多种样式风格选择,多种指示器样式选择。
  9. 所有控件自适应窗体拉伸变化。
  10. 集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。
  11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。
  12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。
  13. 所有控件最后生成一个动态库文件(dll或者so等),可以直接集成到qtcreator中拖曳设计使用。
  14. 目前已经有qml版本,后期会考虑出pyqt版本,如果用户需求量很大的话。
  15. 自定义控件插件开放动态库使用(永久免费),无任何后门和限制,请放心使用。
  16. 目前已提供32个版本的dll,其中qt_5_7_0_mingw530_32这个版本会一直保证最新的完整的。
  17. 不定期增加控件和完善控件,不定期更新SDK,欢迎各位提出建议,谢谢!
  18. Qt入门书籍推荐霍亚飞的《Qt Creator快速入门》《Qt5编程入门》,Qt进阶书籍推荐官方的《C++ GUI Qt4编程》。
  19. 强烈推荐程序员自我修养和规划系列书《大话程序员》《程序员的成长课》《解忧程序员》,受益匪浅,受益终生!
  20. SDK地址:https://gitee.com/feiyangqingyun/QUCSDK https://github.com/feiyangqingyun/qucsdk

Qt编写自定义控件64-垂直时间轴的更多相关文章

  1. Qt编写自定义控件二动画按钮

    现在的web发展越来越快,很多流行的布局样式,都是从web开始的,写惯了Qt widgets 项目,很多时候想改进一下现有的人机交互,尤其是在现有的按钮上加一些动画的效果,例如鼠标移上去变大,移开还原 ...

  2. HTML5+CSS3实现的响应式垂直时间轴

    <!DOCTYPE HTML><html><head><meta charset="utf-8"><meta name=&qu ...

  3. Qt编写自定义控件49-飞机仪表盘

    一.前言 飞行仪表是测定和表示飞机数据的工具,飞机中必不可少的一部分,飞行员根据飞行仪表表示的数据才能正确地做出判断.一般飞机仪表包括高度表+空速表+垂直速率表+姿态仪+航向指示表+转弯协调表. 这次 ...

  4. Qt编写自定义控件插件开放动态库dll使用(永久免费)

    这套控件陆陆续续完善了四年多,目前共133个控件,除了十几个控件参考网友开源的代码写的,其余全部原创,在发布之初就有打算将动态库开放出来永久免费使用,在控件比较完善的今天抽了半天时间编译了多个qt版本 ...

  5. Qt编写自定义控件10-云台仪表盘

    前言 做过安防视频监控的同学都清楚,在视频监控系统软件上都可以看到一个云台控制区域,可以对球机进行下下左右等八个方位的运动控制,还可以进行复位,一般都是美工作图好,然后贴图的形式加入到软件中,好处是程 ...

  6. Qt编写自定义控件59-直方动态图

    一.前言 直方动态图类似于音乐播放时候的柱状图展示,顶部提供一个横线条,当柱状上升的时候,该线条类似于帽子的形式冲到顶端,相当于柱状顶上去的感觉,给人一种动态的感觉,听音乐的同时更加赏心悦目,原理比较 ...

  7. Qt编写自定义控件58-直方对称图

    一.前言 本控件也非原创控件,是参考网上的代码而来的,对称顾名思义就是将画布平均成上下两部分,将设置的值自动按照画布高度的一半作为参照高度进行绘制,然后增加动态过渡效果,有点类似于声音播放时候的频谱效 ...

  8. Qt编写自定义控件56-波浪曲线

    一.前言 波浪曲线控件,其实是之前一个水波进度条控件的一个核心,其实就是利用正弦曲线来生成对应的坐标进行绘制,把这个功能单独提取出来,是为了更详细的研究各种正弦余弦等拓展效果,当时写这个效果的时候,参 ...

  9. Qt编写自定义控件55-手机通讯录

    一.前言 前面几篇文章中的控件基本上难度系数接近0,甚至有凑控件数量的嫌疑,这次必须来一个强悍的控件,本控件难度系数在所有控件中排前五,代码量也不少,头文件都550行,实现文件1600行,为什么这么多 ...

随机推荐

  1. machine learning (5)---learning rate

    degugging:make sure gradient descent is working correctly cost function(J(θ)) of Number of iteration ...

  2. oracle删除重复数据,只保留一条

    比如,某个表要按照id和name重复,就算重复数据 delete from 表名 where rowid not in (select min(rowid) from 表名 group by id,n ...

  3. python - django (ORM使用步骤)

    print('asd') """ # 1. 手动创建一个数据库 # 2. 在 Django 项目中设置连接数据库的相关配置(告诉Django 连接哪一个数据库) 在 DA ...

  4. 指数基金介绍专栏(8):国企指数(H股指数)详细介绍,最新资料解析,看这一篇就够了

    作者:牛大 | 公众号:定投五分钟 大家好,我是牛大.每天五分钟,投资你自己:坚持基金定投,终会财富自由! 昨天牛大给大家介绍了恒生指数,没看的朋友可以去公众号看一下. 指数基金介绍专栏(7):恒生指 ...

  5. 【JS】闭包的理解

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无 ...

  6. bash: cd: too many arguments 报错

    路径名或者变量有空格时候,会造成参数太多的错误提示 解决方法:把空格的地方用引号包括起来

  7. 猴猴的比赛 dfs序

    猴猴的比赛 dfs序 两颗\(n\)节点的树,不相同,问多少点对\((u,v)\)在两棵树上均满足路径\(v\)在\(u\)子树中 \(n\le 10^5\) 暴力: \(n^2\)暴力枚举点对用\( ...

  8. bee api new

    bee api appcode -conn="root:root@tcp(127.0.0.1:3306)/test"

  9. [ZJOI2007][BZOJ1060]时态同步

    Description 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数 字1,2,3….进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路 ...

  10. [洛谷 P4556] 雨天的尾巴

    传送门 Solution 线段树合并的入门题 lca可以在dfs的时候离线求(用并查集) 更新的点有每条链的两个端点,它们的lca和dad[lca] 为了节省空间,lca和dad[lca]的更新可以先 ...