一、前言

天气仪表盘控件是所有控件中唯一一个使用了svg矢量图的控件,各种天气图标采用的矢量图,颜色变换采用动态载入svg的内容更改生成的,其实也可以采用图形字体来做,本次控件为了熟悉下svg在Qt中的使用,才采用的svg来绘制。

天气一般要表示多个内容,温度+湿度+天气等,这就需要合理的布局多种元素的位置才能更加美观一些,这里参照的是网上一些通用的做法,比如最外层圆环是温度,中间圆环湿度,然后天气图标贴在中间圆环里边的左上角,同时再绘制温度湿度的值,动态变化的。

二、实现的功能

  • 1:可设置两种值,比如温度+湿度
  • 2:可设置两种值的背景颜色+文字颜色
  • 3:可设置零度值左侧右侧两种颜色
  • 4:可设置圆的起始角度和结束角度
  • 5:可设置10种天气,晴天+雨天+阴天+大风等
  • 6:可设置各种其他颜色
  • 7:科设置是否启用动画显示进度以及动画步长

三、效果图

四、头文件代码

#ifndef GAUGEWEATHER_H
#define GAUGEWEATHER_H /**
* 天气仪表盘控件 作者:东门吹雪(QQ:709102202) 整理:飞扬青云(QQ:517216493) 2019-4-23
* 1:可设置两种值,比如温度+湿度
* 2:可设置两种值的背景颜色+文字颜色
* 3:可设置零度值左侧右侧两种颜色
* 4:可设置圆的起始角度和结束角度
* 5:可设置10种天气,晴天+雨天+阴天+大风等
* 6:可设置各种其他颜色
* 7:科设置是否启用动画显示进度以及动画步长
*/ #include <QWidget>
#include <QDomElement> #ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif class QDESIGNER_WIDGET_EXPORT GaugeWeather : public QWidget
#else
class GaugeWeather : public QWidget
#endif {
Q_OBJECT
Q_ENUMS(WeatherType) Q_PROPERTY(double outerValue READ getOuterValue WRITE setOuterValue)
Q_PROPERTY(double outerMinValue READ getOuterMinValue WRITE setOuterMinValue)
Q_PROPERTY(double outerMaxValue READ getOuterMaxValue WRITE setOuterMaxValue) Q_PROPERTY(int outerStartAngle READ getOuterStartAngle WRITE setOuterStartAngle)
Q_PROPERTY(int outerEndAngle READ getOuterEndAngle WRITE setOuterEndAngle) Q_PROPERTY(QColor outerRingBgColor READ getOuterRingBgColor WRITE setOuterRingBgColor)
Q_PROPERTY(QColor outerRingColor READ getOuterRingColor WRITE setOuterRingColor) Q_PROPERTY(double innerValue READ getInnerValue WRITE setInnerValue)
Q_PROPERTY(double innerMinValue READ getInnerMinValue WRITE setInnerMinValue)
Q_PROPERTY(double innerMaxValue READ getInnerMaxValue WRITE setInnerMaxValue) Q_PROPERTY(int innerStartAngle READ getInnerStartAngle WRITE setInnerStartAngle)
Q_PROPERTY(int innerEndAngle READ getInnerEndAngle WRITE setInnerEndAngle) Q_PROPERTY(QColor innerRingBgColor READ getInnerRingBgColor WRITE setInnerRingBgColor)
Q_PROPERTY(QColor innerRingNegativeColor READ getInnerNegativeColor WRITE setInnerNegativeColor)
Q_PROPERTY(QColor innerRingPositiveColor READ getInnerPositiveColor WRITE setInnerPositiveColor) Q_PROPERTY(int innerScaleMajor READ getInnerScaleMajor WRITE setInnerScaleMajor)
Q_PROPERTY(int innerScaleMinor READ getInnerScaleMinor WRITE setInnerScaleMinor)
Q_PROPERTY(QColor innerScaleColor READ getInnerScaleColor WRITE setInnerScaleColor)
Q_PROPERTY(QColor innerScaleNumColor READ getInnerScaleNumColor WRITE setInnerScaleNumColor) Q_PROPERTY(QColor centerPixMapNegativeColor READ getCenterPixMapNegativeColor WRITE setCenterPixMapNegativeColor)
Q_PROPERTY(QColor centerPixMapPositiveColor READ getCenterPixMapPositiveColor WRITE setCenterPixMapPositiveColor) Q_PROPERTY(QColor outerValueTextColor READ getOuterValueTextColor WRITE setOuterValueTextColor)
Q_PROPERTY(QColor innerNegativeValueTextColor READ getInnerNegativeValueTextColor WRITE setInnerNegativeValueTextColor)
Q_PROPERTY(QColor innerPositiveValueTextColor READ getInnerPositiveValueTextColor WRITE setInnerPositiveValueTextColor) Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation)
Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep)
Q_PROPERTY(WeatherType weatherType READ getWeatherType WRITE setWeatherType) public:
enum WeatherType {
SUNNY = 0, //晴天
RAINY = 1, //雨天
SNOWY = 2, //雪天
CLOUDY = 3, //多云
WINDY = 4, //风
SNOWY_RAINY = 5, //雪雨
HAIL = 6, //冰雹
LIGHTNING = 7, //闪电
FOG = 8, //雾
PARTLYCLOUDY = 9 //局部多云
}; explicit GaugeWeather(QWidget *parent = 0);
~GaugeWeather(); protected:
void paintEvent(QPaintEvent *);
void drawOuterRingBg(QPainter *painter);
void drawOuterRing(QPainter *painter);
void drawInnerRingBg(QPainter *painter);
void drawInnerRing(QPainter *painter);
void drawInnerRingScale(QPainter *painter);
void drawInnerRingScaleNum(QPainter *painter);
void drawCenterPixMap(QPainter *painter);
void drawValue(QPainter *painter); private slots:
void updateOuterValue(); //更新外圈数值
void updateInnerValue(); //更新内圈数值 private:
double outerMaxValue; //外圈最大值
double outerMinValue; //外圈最小值
double outerValue; //外圈值
double outerCurrValue; //外圈当前值 int outerStartAngle; //外环开始旋转角度
int outerEndAngle; //外环结束旋转角度 QColor outerRingBgColor; //外圈背景色
QColor outerRingColor; //外圈当前色 double innerMaxValue; //内圈最大值
double innerMinValue; //内圈最小值
double innerValue; //内圈值
double innerCurrValue; //内圈当前值 int innerStartAngle; //内环开始旋转角度
int innerEndAngle; //内环结束旋转角度 QColor innerRingBgColor; //内圈背景色
QColor innerRingNegativeColor; //内圈负值当前色
QColor innerRingPositiveColor; //内圈正值当前色 int innerScaleMajor; //内环大刻度数量
int innerScaleMinor; //内环小刻度数量
QColor innerScaleColor; //内环刻度颜色
QColor innerScaleNumColor; //内环刻度值颜色
int precision; //精确度,小数点后几位 QColor centerPixMapNegativeColor; //中心图片颜色
QColor centerPixMapPositiveColor; //中心图片颜色
QString centerSvgPath; //当前svg图片路径
WeatherType weatherType; //天气类型 QColor outerValueTextColor; //外环值文本颜色
QColor innerNegativeValueTextColor; //内环正值文本颜色
QColor innerPositiveValueTextColor; //内环负值文本颜色 bool animation; //是否启用动画显示
double animationStep; //动画显示时步长 bool outerReverse; //是否往回走
bool innerReverse; //是否往回走
bool clockWise; //顺时针 QTimer *outerTimer; //外环定时器绘制动画
QTimer *innerTimer; //内环定时器绘制动画 //将svg文件中的xml数据颜色替换
void setColor(QDomElement elem, QString strtagname, QString strattr, QString strattrval);
QString rgb2HexStr(const QColor &color); public:
double getOuterMinValue() const;
double getOuterMaxValue() const;
double getOuterValue() const;
int getOuterStartAngle() const;
int getOuterEndAngle() const; QColor getOuterRingBgColor() const;
QColor getOuterRingColor() const; double getInnerMaxValue() const;
double getInnerMinValue() const;
double getInnerValue() const;
int getInnerStartAngle() const;
int getInnerEndAngle() const; QColor getInnerRingBgColor() const;
QColor getInnerNegativeColor() const;
QColor getInnerPositiveColor() const; int getInnerScaleMajor() const;
int getInnerScaleMinor() const;
QColor getInnerScaleColor() const;
QColor getInnerScaleNumColor() const; bool getAnimation() const;
double getAnimationStep() const; WeatherType getWeatherType() const; QColor getCenterPixMapNegativeColor() const;
QColor getCenterPixMapPositiveColor() const; QColor getOuterValueTextColor() const;
QColor getInnerNegativeValueTextColor() const;
QColor getInnerPositiveValueTextColor() const; QSize sizeHint() const;
QSize minimumSizeHint() const; public Q_SLOTS:
void setWeatherType(WeatherType &type); //设置范围值
void setOuterRange(double minValue, double maxValue);
//设置外环最大最小值
void setOuterMinValue(double value);
void setOuterMaxValue(double value); //设置外环值
void setOuterValue(double value);
//设置外环开始旋转角度
void setOuterStartAngle(int startAngle);
//设置外环结束旋转角度
void setOuterEndAngle(int endAngle);
//设置外环背景色
void setOuterRingBgColor(const QColor &color);
//设置外环进度色
void setOuterRingColor(const QColor &color); //设置范围值
void setInnerRange(double minValue, double maxValue);
void setInnerMinValue(double value);
void setInnerMaxValue(double value);
void setInnerValue(double value);
void setInnerStartAngle(int startAngle);
void setInnerEndAngle(int endAngle); void setInnerRingBgColor(const QColor &color);
void setInnerNegativeColor(const QColor &color);
void setInnerPositiveColor(const QColor &color); void setInnerScaleMajor(int value);
void setInnerScaleMinor(int value);
void setInnerScaleColor(const QColor &color);
void setInnerScaleNumColor(const QColor &color); //设置中心图标颜色
void setCenterPixMapNegativeColor(const QColor &color);
void setCenterPixMapPositiveColor(const QColor &color); void setOuterValueTextColor(const QColor &color);
void setInnerNegativeValueTextColor(const QColor &color);
void setInnerPositiveValueTextColor(const QColor &color); //设置是否启用动画显示
void setAnimation(bool animation);
//设置动画显示的步长
void setAnimationStep(double animationStep); Q_SIGNALS:
void valueChanged(double value);
}; #endif // GAUGEWEATHER_H

五、核心代码

void GaugeWeather::paintEvent(QPaintEvent *)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height); //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.translate(width / 2, height / 2);
painter.scale(side / 200.0, side / 200.0); //绘制外环背景
drawOuterRingBg(&painter);
//绘制外环进度
drawOuterRing(&painter);
//绘制内环背景
drawInnerRingBg(&painter);
//绘制内环进度
drawInnerRing(&painter);
//绘制内环刻度值
drawInnerRingScaleNum(&painter);
//绘制中心图片
drawCenterPixMap(&painter);
//绘制数值
drawValue(&painter);
} void GaugeWeather::drawOuterRingBg(QPainter *painter)
{
int radius = 99;
painter->save();
painter->setBrush(Qt::NoBrush); //绘制圆弧方法绘制圆环
int penWidth = 13;
QRectF rect(-radius + penWidth / 2, -radius + penWidth / 2, radius * 2 - penWidth, radius * 2 - penWidth);
//可以自行修改画笔的后三个参数,形成各种各样的效果,例如Qt::FlatCap改为Qt::RoundCap可以产生圆角效果
QPen pen(outerRingBgColor, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle); //计算总范围角度
double angleAll = 360.0 - outerStartAngle - outerEndAngle; //绘制总范围角度圆弧
pen.setColor(outerRingBgColor);
painter->setPen(pen);
painter->drawArc(rect, (270 - outerStartAngle - angleAll) * 16, angleAll * 16);
painter->restore();
} void GaugeWeather::drawOuterRing(QPainter *painter)
{
int radius = 99;
painter->save();
painter->setBrush(Qt::NoBrush); //绘制圆弧方法绘制圆环
int penWidth = 13;
QRectF rect(-radius + penWidth / 2, -radius + penWidth / 2, radius * 2 - penWidth, radius * 2 - penWidth);
//可以自行修改画笔的后三个参数,形成各种各样的效果,例如Qt::FlatCap改为Qt::RoundCap可以产生圆角效果
QPen pen(outerRingColor, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle); //计算总范围角度,当前值范围角度,剩余值范围角度
double angleAll = 360.0 - outerStartAngle - outerEndAngle;
double angleCurrent = angleAll * ((outerCurrValue - outerMinValue) / (outerMaxValue - outerMinValue)); //绘制当前值饼圆
painter->setPen(pen);
painter->drawArc(rect, (270 - outerStartAngle - angleCurrent) * 16, angleCurrent * 16);
painter->restore();
} void GaugeWeather::drawInnerRingBg(QPainter *painter)
{
int radius = 77;
painter->save();
painter->setBrush(Qt::NoBrush); double penWidth = 13;
QPen pen(innerRingBgColor, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle);
painter->setPen(pen); double angleAll = 360.0 - innerStartAngle - innerEndAngle;
QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2); //零值以上背景
painter->drawArc(rect, (270 - innerStartAngle - angleAll) * 16 , angleAll * 16);
//零值以下背景
//painter->drawArc(rect,(270 -innerStartAngle - null2MinAngle) * 16 ,null2MinAngle * 16); painter->restore();
} void GaugeWeather::drawInnerRing(QPainter *painter)
{
int radius = 77;
painter->save();
painter->setBrush(Qt::NoBrush); int penWidth = 13.5;
QPen pen(innerRingPositiveColor, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle); double angleAll = 360.0 - innerStartAngle - innerEndAngle;
double null2MinAngle = angleAll * (( 0 - innerMinValue) / (innerMaxValue - innerMinValue)); //零点所占的角度
double nullUpAllAngle = angleAll - null2MinAngle; //正基本角度
double currAngle;
if(innerCurrValue >= 0) {
//正角度
pen.setColor(innerRingNegativeColor);
currAngle = nullUpAllAngle * (innerCurrValue / innerMaxValue) * -1;
} else {
//负角度
pen.setColor(innerRingPositiveColor);
currAngle = null2MinAngle * (innerCurrValue / innerMinValue);
} painter->setPen(pen); QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
painter->drawArc(rect, (270 - innerStartAngle - null2MinAngle) * 16 , currAngle * 16); painter->restore(); } void GaugeWeather::drawInnerRingScale(QPainter *painter)
{
int radius = 76;
painter->save();
painter->setPen(innerScaleColor); painter->rotate(innerStartAngle);
int steps = (innerScaleMajor * innerScaleMinor);
double angleStep = (360.0 - innerStartAngle - innerEndAngle) / steps;
QPen pen = painter->pen();
pen.setCapStyle(Qt::RoundCap); for (int i = 0; i <= steps; i++) {
if (i % innerScaleMinor == 0) {
pen.setWidthF(1.5);
painter->setPen(pen);
painter->drawLine(0, radius - 12, 0, radius);
} else {
pen.setWidthF(1.0);
painter->setPen(pen);
painter->drawLine(0, radius - 5, 0, radius);
} painter->rotate(angleStep);
} painter->restore();
}

六、控件介绍

  1. 超过150个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。
  2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。
  3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.12的任何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动态库文件,可以直接集成到qtcreator中拖曳设计使用。
  14. 目前已经有qml版本,后期会考虑出pyqt版本,如果用户需求量很大的话。

七、SDK下载

  • SDK下载链接:https://pan.baidu.com/s/1A5Gd77kExm8Co5ckT51vvQ 提取码:877p
  • 下载链接中包含了各个版本的动态库文件,所有控件的头文件,使用demo,自定义控件+属性设计器。
  • 自定义控件插件开放动态库dll使用(永久免费),无任何后门和限制,请放心使用。
  • 目前已提供26个版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
  • 不定期增加控件和完善控件,不定期更新SDK,欢迎各位提出建议,谢谢!
  • widget版本(QQ:517216493)qml版本(QQ:373955953)三峰驼(QQ:278969898)。
  • 涛哥的知乎专栏 Qt进阶之路 https://zhuanlan.zhihu.com/TaoQt
  • 欢迎关注微信公众号【高效程序员】,C++/Python、学习方法、写作技巧、热门技术、职场发展等内容,干货多多,福利多多!
  • Qt入门书籍推荐霍亚飞的《Qt Creator快速入门》《Qt5编程入门》,Qt进阶书籍推荐官方的《C++ GUI Qt4编程》。
  • 强烈推荐程序员自我修养和规划系列书《大话程序员》《程序员的成长课》《解忧程序员》!

Qt编写自定义控件44-天气仪表盘的更多相关文章

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

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

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

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

  3. Qt编写自定义控件4-旋转仪表盘

    前言 旋转仪表盘,一般用在需要触摸调节设置值的场景中,其实Qt本身就提供了QDial控件具有类似的功能,本控件最大的难点不在于绘制刻度和指针等,而在于自动计算当前用户按下处的坐标转换为当前值,这个功能 ...

  4. Qt编写自定义控件3-速度仪表盘

    前言 速度仪表盘,写作之初的本意是用来展示当前测试的网速用的,三色圆环+数码管显示当前速度,Qt自带了数码管控件QLCDNumber,直接集成即可,同时还带有动画功能,其实也可以用在汽车+工业领域等, ...

  5. Qt编写自定义控件1-汽车仪表盘

    前言 汽车仪表盘几乎是qt写仪表盘控件中最常见的,一般来说先要求美工做好设计图,然后设计效果图给到程序员,由程序员根据效果来实现,主要靠贴图,这种方法有个好处就是做出来的效果比较逼真,和真实效果图基本 ...

  6. Qt编写自定义控件12-进度仪表盘

    前言 进度仪表盘主要应用场景是标识一个任务进度完成的状况等,可以自由的设置范围值和当前值,为了美观还提供了四种指示器(圆形指示器/指针指示器/圆角指针指示器/三角形指示器),各种颜色都可以设置,其中的 ...

  7. Qt编写自定义控件54-时钟仪表盘

    一.前言 这个控件没有太多的应用场景,主要就是练手,论美观的话比不上之前发过的一个图片时钟控件,所以此控件也是作为一个基础的绘制demo出现在Qt源码中,我们可以在Qt的安装目录下找到一个时钟控件的绘 ...

  8. Qt编写自定义控件51-可输入仪表盘

    一.前言 这个控件是近期定制的控件,还是比较实用的控件之一,用户主要是提了三点需求,一点是切换焦点的时候控件放大突出显示,一点是可直接输入或者编辑值,还有一点是支持上下键及翻页键和鼠标滚轮来动态修改值 ...

  9. Qt编写自定义控件50-迷你仪表盘

    一.前言 这个控件取名叫迷你仪表盘,是以为该控件可以缩小到很小很小的区域显示,非常适合小面积区域展示仪表数据使用,还可以手动触摸调节进度,是我个人觉得最漂亮小巧的一个控件.初次看到类似的控件是在一个音 ...

随机推荐

  1. 进程、requests模块的简单使用

    一.进程 1.进程间数据不共享 import multiprocessing data_list = [] def task(arg): data_list.append(arg) print(dat ...

  2. 赤池信息准则AIC,BIC

    很多参数估计问题均采用似然函数作为目标函数,当训练数据足够多时,可以不断提高模型精度,但是以提高模型复杂度为代价的,同时带来一个机器学习中非常普遍的问题——过拟合.所以,模型选择问题在模型复杂度与模型 ...

  3. How to parse unix timestamp to time.Time

      The time.Parse function does not do Unix timestamps. Instead you can use strconv.ParseInt to parse ...

  4. 在vue中使用css预编辑器

    vue中使用less 安装less依赖,npm install less less-loader --save vue中使用sass npm install --save-dev sass-loade ...

  5. CF277B Set of Points——构造题

    题意 构造 $n$ 个点使其凸度(顶点数最多的凸多边形的顶点数)恰好为 $m$,且任意三点不能共线. (题意有点绕,建议看英文原文 分析 首先,题目并不是求凸包上的顶点数,而是求能形成的凸多边形的最大 ...

  6. [bzoj 2393] Cirno的完美算数教室 (容斥原理+dfs剪枝)

    题目描述 CirnoCirnoCirno发现了一种bakabakabaka数,这种数呢只含有222和999两种数字 现在CirnoCirnoCirno想知道[L,R][L,R][L,R]中有多少个数能 ...

  7. bootstrap之collapse

    <div class="container"> <!--该button可以控制div是否显示 1.首先给button设置data-toggle="col ...

  8. Neo4j 快速清除数据库数据

    在开发过程中,很多时候需要快(简)速(单)清(粗)除(暴)Neo4j中存在的海量数据节点和关系数据.在这种情况下,delete和detach从性能上都已力不从心.Neo4j官方推荐清库方法,即删除gr ...

  9. Postgresql vacuum freeze相关参数

    先看3个参数:autovacuum_freeze_max_age           | 500000vacuum_freeze_min_age               | 10vacuum_fr ...

  10. 浅谈"$fake$树"——虚树

    树形$dp$利器——"$fake$"树(虚树$qwq$)  前置知识: $1.$$dfs$序 $2.$倍增法或者树链剖分求$lca$  问题引入: 在许多的树形动规中,很多时候点特 ...