一、前言

在Qt自定义控件中,仪表盘控件是数量最多的,写仪表盘都写到快要吐血,可能是因为各种工业控制领域用的比较多吧,而且仪表盘又是比较生动直观的,这次看到百度的echart中有这个控件,所以也来模仿做了一个,其实掌握了一两个仪表盘的绘制方法以后,其他仪表盘的绘制都是如鱼得水,基本上变化很小。总结起来就如下几点:

1:仪表盘边框

2:刻度尺

3:刻度值

4:圆环进度

5:指针

6:当前值

7:仪表盘标题

无论什么仪表盘,基本上包含的上面几个要素的大部分,所以只要掌握几个要素的绘制,任何仪表盘绘制都是轻轻松松信手拈来。无非就是有些仪表盘要求刻度尺在里边有些要求在外边,有些要求有圆环进度不同颜色显示,有些要求可以自定义左侧起始角度和右侧结束角度,有些要求指针圆形方形椭圆形等,有些要求值改变的时候带一些缓慢的动画过渡效果等。

二、实现的功能

  • 1:可设置范围值,支持负数值
  • 2:可设置精确度+刻度尺精确度,最大支持小数点后3位
  • 3:可设置大刻度数量/小刻度数量
  • 4:可设置开始旋转角度/结束旋转角度
  • 5:可设置是否启用动画效果以及动画效果每次移动的步长
  • 6:可设置刻度颜色+文字颜色+圆环的宽度和颜色
  • 7:自适应窗体拉伸,刻度尺和文字自动缩放
  • 8:可设置单位以及仪表盘名称

三、效果图

四、头文件代码

#ifndef GAUGEPANEL_H
#define GAUGEPANEL_H /**
* 面板仪表盘控件 作者:feiyangqingyun(QQ:517216493) 2019-7-3
* 1:可设置范围值,支持负数值
* 2:可设置精确度+刻度尺精确度,最大支持小数点后3位
* 3:可设置大刻度数量/小刻度数量
* 4:可设置开始旋转角度/结束旋转角度
* 5:可设置是否启用动画效果以及动画效果每次移动的步长
* 6:可设置刻度颜色+文字颜色+圆环的宽度和颜色
* 7:自适应窗体拉伸,刻度尺和文字自动缩放
* 8:可设置单位以及仪表盘名称
*/ #include <QWidget> #ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif class QDESIGNER_WIDGET_EXPORT GaugePanel : public QWidget
#else
class GaugePanel : public QWidget
#endif {
Q_OBJECT
Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue)
Q_PROPERTY(double value READ getValue WRITE setValue)
Q_PROPERTY(int precision READ getPrecision WRITE setPrecision)
Q_PROPERTY(int scalePrecision READ getScalePrecision WRITE setScalePrecision) Q_PROPERTY(int scaleMajor READ getScaleMajor WRITE setScaleMajor)
Q_PROPERTY(int scaleMinor READ getScaleMinor WRITE setScaleMinor)
Q_PROPERTY(int startAngle READ getStartAngle WRITE setStartAngle)
Q_PROPERTY(int endAngle READ getEndAngle WRITE setEndAngle) Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation)
Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep) Q_PROPERTY(int ringWidth READ getRingWidth WRITE setRingWidth)
Q_PROPERTY(QColor ringColor READ getRingColor WRITE setRingColor) Q_PROPERTY(QColor scaleColor READ getScaleColor WRITE setScaleColor)
Q_PROPERTY(QColor pointerColor READ getPointerColor WRITE setPointerColor)
Q_PROPERTY(QColor bgColor READ getBgColor WRITE setBgColor)
Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
Q_PROPERTY(QString unit READ getUnit WRITE setUnit)
Q_PROPERTY(QString text READ getText WRITE setText) public:
explicit GaugePanel(QWidget *parent = 0);
~GaugePanel(); protected:
void paintEvent(QPaintEvent *);
void drawRing(QPainter *painter);
void drawScale(QPainter *painter);
void drawScaleNum(QPainter *painter);
void drawPointer(QPainter *painter);
void drawValue(QPainter *painter); private slots:
void updateValue(); private:
double minValue; //最小值
double maxValue; //最大值
double value; //目标值
int precision; //精确度,小数点后几位
int scalePrecision; //刻度尺精确度,小数点后几位 int scaleMajor; //大刻度数量
int scaleMinor; //小刻度数量
int startAngle; //开始旋转角度
int endAngle; //结束旋转角度 bool animation; //是否启用动画显示
double animationStep; //动画显示时步长 int ringWidth; //圆环宽度
QColor ringColor; //圆环颜色 QColor scaleColor; //刻度颜色
QColor pointerColor; //指针颜色
QColor bgColor; //背景颜色
QColor textColor; //文字颜色
QString unit; //单位
QString text; //描述文字 bool reverse; //是否往回走
double currentValue; //当前值
QTimer *timer; //定时器绘制动画 public:
double getMinValue() const;
double getMaxValue() const;
double getValue() const;
int getPrecision() const;
int getScalePrecision() const; int getScaleMajor() const;
int getScaleMinor() const;
int getStartAngle() const;
int getEndAngle() const; bool getAnimation() const;
double getAnimationStep() const; int getRingWidth() const;
QColor getRingColor() const; QColor getScaleColor() const;
QColor getPointerColor() const;
QColor getBgColor() const;
QColor getTextColor() const;
QString getUnit() const;
QString getText() const; QSize sizeHint() const;
QSize minimumSizeHint() const; public Q_SLOTS:
//设置范围值
void setRange(double minValue, double maxValue);
void setRange(int minValue, int maxValue); //设置最大最小值
void setMinValue(double minValue);
void setMaxValue(double maxValue); //设置目标值
void setValue(double value);
void setValue(int value); //设置精确度
void setPrecision(int precision);
//设置刻度尺精确度
void setScalePrecision(int scalePrecision); //设置主刻度数量
void setScaleMajor(int scaleMajor);
//设置小刻度数量
void setScaleMinor(int scaleMinor);
//设置开始旋转角度
void setStartAngle(int startAngle);
//设置结束旋转角度
void setEndAngle(int endAngle); //设置是否启用动画显示
void setAnimation(bool animation);
//设置动画显示的步长
void setAnimationStep(double animationStep); //设置圆环宽度+颜色
void setRingWidth(int ringWidth);
void setRingColor(const QColor &ringColor); //设置刻度颜色
void setScaleColor(const QColor &scaleColor);
//设置指针颜色
void setPointerColor(const QColor &pointerColor);
//设置背景颜色
void setBgColor(const QColor &bgColor);
//设置文本颜色
void setTextColor(const QColor &textColor);
//设置单位
void setUnit(const QString &unit);
//设置中间描述文字
void setText(const QString &text); Q_SIGNALS:
void valueChanged(int value);
}; #endif // GAUGEPANEL_H

五、核心代码

void GaugePanel::paintEvent(QPaintEvent *)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height); //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //绘制背景
if (bgColor != Qt::transparent) {
painter.setPen(Qt::NoPen);
painter.fillRect(this->rect(), bgColor);
} painter.translate(width / 2, height / 2);
painter.scale(side / 200.0, side / 200.0); //绘制圆环
drawRing(&painter); //绘制刻度线
drawScale(&painter); //绘制刻度值
drawScaleNum(&painter); //绘制指示器
drawPointer(&painter); //绘制当前值
drawValue(&painter);
} void GaugePanel::drawRing(QPainter *painter)
{
int radius = 70;
painter->save(); QPen pen;
pen.setCapStyle(Qt::FlatCap);
pen.setWidthF(ringWidth);
pen.setColor(ringColor);
painter->setPen(pen); radius = radius - ringWidth;
QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
double angleAll = 360.0 - startAngle - endAngle;
painter->drawArc(rect, (270 - startAngle - angleAll) * 16, angleAll * 16); painter->restore();
} void GaugePanel::drawScale(QPainter *painter)
{
int radius = 80;
painter->save(); painter->rotate(startAngle);
int steps = (scaleMajor * scaleMinor);
double angleStep = (360.0 - startAngle - endAngle) / steps; QPen pen;
pen.setCapStyle(Qt::RoundCap);
pen.setColor(scaleColor); for (int i = 0; i <= steps; i++) {
if (i % scaleMinor == 0) {
pen.setWidthF(1.5);
painter->setPen(pen);
painter->drawLine(0, radius - 8, 0, radius + 5);
} else {
pen.setWidthF(0.5);
painter->setPen(pen);
painter->drawLine(0, radius - 8, 0, radius - 3);
} painter->rotate(angleStep);
} painter->restore();
} void GaugePanel::drawScaleNum(QPainter *painter)
{
int radius = 95;
painter->save();
painter->setPen(scaleColor); double startRad = (360 - startAngle - 90) * (M_PI / 180);
double deltaRad = (360 - startAngle - endAngle) * (M_PI / 180) / scaleMajor; for (int i = 0; i <= scaleMajor; i++) {
double sina = qSin(startRad - i * deltaRad);
double cosa = qCos(startRad - i * deltaRad);
double value = 1.0 * i * ((maxValue - minValue) / scaleMajor) + minValue; QString strValue = QString("%1").arg((double)value, 0, 'f', scalePrecision);
double textWidth = fontMetrics().width(strValue);
double textHeight = fontMetrics().height();
int x = radius * cosa - textWidth / 2;
int y = -radius * sina + textHeight / 4;
painter->drawText(x, y, strValue);
} painter->restore();
} void GaugePanel::drawPointer(QPainter *painter)
{
int radius = 70;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(pointerColor); QPolygon pts;
pts.setPoints(4, -5, 0, 0, -8, 5, 0, 0, radius); painter->rotate(startAngle);
double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
painter->rotate(degRotate);
painter->drawConvexPolygon(pts); painter->restore();
} void GaugePanel::drawValue(QPainter *painter)
{
int radius = 100;
painter->save();
painter->setPen(textColor); QFont font;
font.setPixelSize(15);
painter->setFont(font); QString strValue = QString("%1").arg((double)currentValue, 0, 'f', precision);
strValue = QString("%1 %2").arg(strValue).arg(unit);
QRectF valueRect(-radius, radius / 3.5, radius * 2, radius / 3.5);
painter->drawText(valueRect, Qt::AlignCenter, strValue); QRectF textRect(-radius, radius / 2.5, radius * 2, radius / 2.5);
font.setPixelSize(12);
painter->setFont(font);
painter->drawText(textRect, Qt::AlignCenter, text); painter->restore();
}

六、控件介绍

  1. 超过149个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,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编写自定义控件31-面板仪表盘控件的更多相关文章

  1. Qt编写自定义控件48-面板窗体控件

    一.前言 很多时候需要有一个控件,能够替代容器控件,自动容纳多个widget,自适应宽高,然后提供滚动条功能,这就必然需要用到QScrollArea控件,可设置各个子面板的间距等,也在很多系统中用到, ...

  2. Qt编写自定义控件47-面板区域控件

    一.前言 在很多web网页上,经常可以看到一个设备对应一个面板,或者某种同等类型的信息全部放在一个面板上,该面板还可以拖来拖去的,这个控件首次用在智能访客管理平台中,比如身份证信息一个面板,访客信息一 ...

  3. Qt编写自定义控件9-导航按钮控件

    前言 导航按钮控件,主要用于各种漂亮精美的导航条,我们经常在web中看到导航条都非常精美,都是html+css+js实现的,还自带动画过度效果,Qt提供的qss其实也是无敌的,支持基本上所有的CSS2 ...

  4. Qt编写自定义控件45-柱状标尺控件

    一.前言 这个控件写了很久了,是最早期的一批控件中的一个,和温度计控件类似,都是垂直的进度条,可以设置不同的背景颜色,左侧的刻度也可以自由设定,还提供了动画效果,其实就是开启定时器慢慢的进度到设定的目 ...

  5. Qt编写自定义控件35-GIF录屏控件

    一.前言 在平时的写作过程中,经常需要将一些操作动作和效果图截图成gif格式,使得涵盖的信息更全面更生动,有时候可以将整个操作过程和运行效果录制成MP4,但是文件体积比较大,而且很多网站不便于上传,基 ...

  6. Qt编写自定义控件26-平铺背景控件

    一.前言 平铺背景控件,主要的应用场景是作为画布出现,黑白相间的背景图,然后上面可以放置图片图形等,使得看起来更美观,比如PS软件新建图层以后的背景,FireWorks软件新建画布以后的透明背景,IC ...

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

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

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

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

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

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

随机推荐

  1. 三星Q470c Logo界面无限掉电重启,变砖后的挽救过程

    背景 三星笔记本的部分型号如:NP530 Q470等 安装win8后再次重装系统(我弄了个Ubuntu18)会导致无法进入BIOS菜单页面的问题.启动显示logo页面后,能够听到明显啪的一声(硬盘掉电 ...

  2. [HNOI2007]分裂游戏 SG打表博弈

    结论:其实每一个巧克力都是一堆石子 它的石子数就是它到队尾的距离 打一个SG表即可 #include<bits/stdc++.h> using namespace std; typedef ...

  3. evpp http server定制实现

    evpp http server定制实现 evpp http server定制实现 evpp http server定制实现

  4. 一个基于TCP/IP的小项目,实现广播消息的功能。(超详细版)

    1.结合现状 功能分析 该功能基于上个项目的改进,主要是通过对服务器端代码的修改,以及对客户端作少许修改,实现开启多客户端时,一个客户端发送消息,达到对所有客户端广播的效果.可参考网吧里的点歌系统,比 ...

  5. SVN错误之“copy admin area is missing”

    1.将对应冲突的文件夹备份一份 2.再复制一份到别的地方,资源管理器搜索.svn全部删除掉 3.删掉本地svn目录里的冲突文件,update一下父目录,显示ok 4.把刚才删掉.svn的目录复制覆盖过 ...

  6. php MySQL 查询数据

    以下为在MySQL数据库中查询数据通用的 SELECT 语法: SELECT column_name,column_name FROM table_name [WHERE Clause] [LIMIT ...

  7. pyecharts v1 版本 学习笔记 散点图

    散点图 基本案例 from example.commons import Faker from pyecharts import options as opts from pyecharts.char ...

  8. How to change the default browser in Visual Studio

    http://www.hanselman.com/blog/HowToChangeTheDefaultBrowserInVisualStudioProgrammaticallyWithPowerShe ...

  9. 检查errno

    转自 http://blog.csdn.net/todd911/article/details/9132095 很多库函数,特别是那些与操作系统有关的,当执行失败时会通过一个名称为errno的外部变量 ...

  10. rep stos ptr dword es:[edi]

    今天读代码时,忽然跳出如下一条指令==>>汇编代码: rep stos dword ptr es:[edi] 在网上查了相关资料显示:/************************** ...