仪表盘制作

相关的基础知识

  • QPainter用来执行具体的绘图相关的操作,用来画点,线,填充,变换,alpha/阿尔法通道(透明度)
    Appha的值越大,就越不透明,范围是0-255,255就是不透明,0就是完全透明;当对应 RGB 颜色时,Alpha 会叠加到颜色上面;只有当 Alpha 通道是255时,才是其真正的颜色。

  • QPainterDevice是Qpainter用来绘图设备,Qt中有几种绘图的设备,如QWidget,Qpainter,QPaxmip

    都是从QPainterDevice继承的。例如QPainter painter(this); 把绘图设备指针传递painter,把当前控件指针初始化。

  • QPainterEngine类提供了不同类型设备接口,对程序员不透明,由QPainter,QpaintDevive类进行交互
    一个绘图的操作流程就是:对一个QPainterDevice直接或间接调用Qpainter类。Qpainter类内部调用QpaintEngine进行绘图,而QPainterEngine类通常是由QPainterDevice类负责创建和管理。

  • Qwidget类,最低层的类,接收鼠标,键盘和从其他敞口系统的事件,并且绘制在屏幕上。

  • QPaintDevice类是所有可以绘制的对象的基类。个绘制设备就是一个可以使用QPainter来绘制的二维空间的抽象。绘画的能力由子类QWidget、QPixmap、QPicture和QPrinter来实现。绘制设备的默认坐标系统的原点在左上角。X向右增加,Y向下增加。单位是一个像素。这里有几种方法在使用绘制工具时来设置用户自定义的坐标系统,

  • Qt 绘图系统定义了两个绘制时使用的关键属性:画刷和画笔。(1)画刷使用QBrush描述,大多用于填充;(2)画笔使用QPen描述,大多用于绘制轮廓线。

  • QBrush定义了QPainter的填充模式,具有样式、颜色、渐变以及纹理等属性。画刷的style()定义了填充的样式,使用Qt::BrushStyle枚举,默认值是Qt::NoBrush,也就是不进行任何填充。QPen定义了用于QPainter应该怎样画线或者轮廓线。画笔具有样式、宽度、画刷、笔帽样式和连接样式等属性。画笔的样式style()定义了线的样式。画刷brush()用于填充画笔所绘制的线条。

绘图的基本函数

//Meter.cpp
#include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent)
{
}Widget::~Widget()
{}
void Widget::paintEvent(QPaintEvent *) //重绘函数
{QPainter painter(this);//一个类中的this表示一个指向该类自己的指针painter.setRenderHint(QPainter::Antialiasing);  /* 使用反锯齿(如果可用) */painter.translate(width() / 2, height() / 2);  /* 坐标变换为窗体中心 */int side = qMin(width(), height());painter.scale(side / 200.0, side / 200.0);       /* 比例缩放 */}
//Meter.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = 0);~Widget();
public:void paintEvent(QPaintEvent *);
};#endif // WIDGET_H

上面的代码是能够绘画出图片的重要函数-重绘函数。只要出现以下几种情况,系统就会自动调用paintEvent方法。

  • a)当窗口部件第一次显示时,系统会自动产生一个绘图事件
  • b)重新调整窗口部件大小
  • c)当窗口部件被其他部件遮挡,然后又再次显示出来时,就会对隐藏的区域产生一个重绘事件
    ranslate(qreal dx, qreal dy);坐标变换可以看做是painter当前的一个状态,我们可以用save()方法把当前的状态存到一个堆栈里,在用过 之后,再用restore()恢复

坐标系统在绘制的过程中是至关重要的,首先做好坐标变换,把窗体的中心设置成坐标原点,(默认的坐标原点的窗体的左上方(0,0)向右是x->增长,向下是y->增长。)

以画仪表盘为例。

  • 首先就要绘制出两个个圆形,设置圆形的背景色,背景色采用渐变填充的方式,通过两个设置两个圆不同的填充颜色来形成一个色环,形成表冠。函数如下。使用的是线性渐变(QLinearGradient)
    。QLinearGradient(qreal xStart, qreal yStart, qreal xFinalStop, qreal yFinalStop);使用这个类实例化一个对象。对象的四个参数,分别是 两个点的坐标,表示渐变的方向。
    setColorAt(qreal pos, const QColor &color); pos是一个[0,1]的闭区间的数字。设置渐变坐标所表示的距离。的比例大小,0.2就是长度的1/5
    painter->save();与painter->restore();基本上都是一起出现的,前者是保存当前坐标,然后进行变换操,后者是将以前的坐标系状 态恢复,其实就是一个入栈和出栈的操作。
void Widget ::drawCrown(QPainter *painter)   //绘制表冠
{painter->save();int radius = 100;    QLinearGradient lg1(0, -radius, 0, radius);  lg1.setColorAt(0, Qt::white);  //设置渐变的颜色和路径比例lg1.setColorAt(1, Qt::gray);   //只是粗略的颜色,具体的可以参考RGB颜色查询对照表painter->setBrush(lg1);   // 创建QBrush对象,把这个渐变对象传递进去:painter->setPen(Qt::NoPen); //边框线无色painter->drawEllipse(-rad   ius, -radius, radius << 1, radius << 1);painter->setBrush(m_background = Qt::black);painter->drawEllipse(-92, -92, 184, 184);painter->restore();
}

接下来是绘制刻度值,沿着圆周的方向,绘制刻度数字

通过一套算法来实现绘制数字刻度

void Widget ::drawScaleNum(QPainter *painter)  //绘制刻度数字
{painter->save();         painter->setPen(m_foreground);//m_startAngle是起始角度,m_endAngle是结束角度,m_scaleMajor在一个量程中分成的刻度数double startRad = ( 270-m_startAngle) * (3.14 / 180);double deltaRad = (360 - m_startAngle - m_endAngle) * (3.14 / 180) / m_scaleMajor;double sina,cosa;int x, y;QFontMetricsF fm(this->font());double w, h, tmpVal;QString str;for (int i = 0; i <= m_scaleMajor; i++){sina = sin(startRad - i * deltaRad);cosa = cos(startRad - i * deltaRad);tmpVal = 1.0 * i *((m_maxValue - m_minValue) / m_scaleMajor) + m_minValue;// tmpVal = 50;str = QString( "%1" ).arg(tmpVal);  //%1作为占位符   arg()函数比起 sprintf()来是类型安全的w = fm.size(Qt::TextSingleLine,str).width();h = fm.size(Qt::TextSingleLine,str).height();x = 82 * cosa - w / 2;y = -82 * sina + h / 4;painter->drawText(x, y, str); //函数的前两个参数是显示的坐标位置,后一个是显示的内容,是字符类型""}painter->restore();
}

在分好的刻度中绘制刻度线
rotate(qreal a);函数实现角度的旋转

void Widget ::drawScale(QPainter *painter)  //绘制刻度线
{painter->save();painter->rotate(m_startAngle);int steps = (m_scaleMajor * m_scaleMinor); //相乘后的值是分的份数double angleStep = (360.0 - m_startAngle - m_endAngle) / steps;  //每一个份数的角度//  painter->setPen(m_foreground); //m_foreground是颜色的设置//  QPen pen = painter->pen();  //第一种方法QPen pen ;pen.setColor(Qt::green);  //推荐使用第二种方式for (int i = 0; i <= steps; i++){if (i % m_scaleMinor == 0)//整数刻度显示加粗{pen.setWidth(1);             //设置线宽painter->setPen(pen);   //使用面向对象的思想,把画笔关联上画家。通过画家画出来painter->drawLine(0, 62, 0, 72); //两个参数应该是两个坐标值}else{pen.setWidth(0);painter->setPen(pen);painter->drawLine(0, 67, 0, 72);}painter->rotate(angleStep);}painter->restore();
}

绘制标题

void Widget ::drawTitle(QPainter *painter)
{painter->save();painter->setPen(m_foreground);//painter->setBrush(m_foreground);QString str(m_title); //显示仪表的功能QFontMetricsF fm(this->font());double w = fm.size(Qt::TextSingleLine,str).width();painter->drawText(-w / 2, -30, str);painter->restore();
}

显示的单位,与数值

void Widget ::drawNumericValue(QPainter *painter)
{QString str  =  QString("%1 %2").arg(m_value, 0, 'f', m_precision).arg(m_units);QFontMetricsF fm(font());double w = fm.size(Qt::TextSingleLine,str).width();painter->setPen(m_foreground);painter->drawText(-w / 2, 42, str);
}

绘制表针,和中心点

void Widget ::drawIndicator(QPainter *painter)
{painter->save();QPolygon pts;pts.setPoints(3, -2,0, 2,0, 0,60); /* (-2,0)/(2,0)/(0,60) *///第一个参数是 ,坐标的个数。后边的是坐标painter->rotate(m_startAngle);double degRotate =  (360.0 - m_startAngle - m_endAngle)/(m_maxValue - m_minValue)*(m_value - m_minValue);//画指针painter->rotate(degRotate);  //顺时针旋转坐标系统QRadialGradient haloGradient(0, 0, 60, 0, 0);  //辐射渐变haloGradient.setColorAt(0, QColor(60,60,60));haloGradient.setColorAt(1, QColor(160,160,160)); //灰painter->setPen(Qt::white); //定义线条文本颜色  设置线条的颜色painter->setBrush(haloGradient);//刷子定义形状如何填满 填充后的颜色painter->drawConvexPolygon(pts); //这是个重载函数,绘制多边形。painter->restore();//画中心点QColor niceBlue(150, 150, 200);QConicalGradient coneGradient(0, 0, -90.0);  //角度渐变coneGradient.setColorAt(0.0, Qt::darkGray);coneGradient.setColorAt(0.2, niceBlue);coneGradient.setColorAt(0.5, Qt::white);coneGradient.setColorAt(1.0, Qt::darkGray);painter->setPen(Qt::NoPen);  //没有线,填满没有边界painter->setBrush(coneGradient);painter->drawEllipse(-5, -5, 10, 10);
}

重绘函数

void Widget ::paintEvent(QPaintEvent *)
{ QPainter painter(this);//一个类中的this表示一个指向该类自己的指针painter.setRenderHint(QPainter::Antialiasing);     /* 使用反锯齿(如果可用) */painter.translate(width() / 2, height() / 2);  /* 坐标变换为窗体中心 */int side = qMin(width(), height());painter.scale(side / 200.0, side / 200.0);       /* 比例缩放 */drawCrown(&painter);                                  /* 画表盘边框 */drawScaleNum(&painter);                          /* 画刻度数值值 */drawScale(&painter);                                    /* 画刻度线 */drawTitle(&painter);                                      /* 画单位 */drawNumericValue(&painter);                        /* 画数字显示 */drawIndicator(&painter);                             /* 画表针 */}

构造函数的初始化


#include "myspeed.h"
#include <QPainter>
#include <qmath.h>Widget ::Widget (QWidget *parent): Widget (parent)
{m_updateTimer = new QTimer(this);m_updateTimer->setInterval(50);//间隔,微妙微单位,大家可以改一下这个值看看转动速度。m_startAngle = 0;  //0刻度的起始角度m_endAngle = 30;m_foreground = Qt::green;m_background = Qt::black; //定义背景颜色m_scaleMajor = 10;//刻度m_scaleMinor = 5; //每个刻度分成5个分度m_minValue = 0;m_maxValue = 100;m_numericIndicatorEnabled = true;m_units = "km/h";m_title = "时速表";m_precision = 0;m_value=0;connect(m_updateTimer,SIGNAL(timeout()),this,SLOT(UpdateAngle()));m_updateTimer->start();//启动定时器// setWindowFlags(Qt::FramelessWindowHint);//无窗体// setAttribute(Qt::WA_TranslucentBackground);//背景透明resize(400, 400);
}

定时

void Widget ::UpdateAngle()
{m_value += 1;if(m_value > 100){m_value = 0;}update();//刷新控件,会调用paintEvent函数
}

头文件

#ifndef MYSPEED_H
#define MYSPEED_H#include <QMainWindow>
#include <QWidget>
#include <QTimer>
class Widget : public Widget
{Q_OBJECTpublic:Widget (QWidget *parent = 0);~Widget ();
protected:void thresholdManager();void paintEvent(QPaintEvent *);void drawCrown(QPainter *painter);void drawBackground(QPainter *painter);void drawScale(QPainter *painter);void drawScaleNum(QPainter *painter);void drawTitle(QPainter *painter);void drawIndicator(QPainter *painter);void drawNumericValue(QPainter *painter);private:bool m_numericIndicatorEnabled;QColor m_crownColor;QColor m_foreground;QColor m_background;QString m_units;QString m_title;int m_scaleMajor;int m_scaleMinor;int m_maxValue, m_minValue;int m_startAngle,m_endAngle;double m_value;int m_precision;QTimer *m_updateTimer;
public Q_SLOTS:void UpdateAngle();
};
#endif // MYSPEED_H

表盘中海添加了定时器,来实现动态的效果

源代码下载

http://download.csdn.net/detail/osean_li/9758894

Qt实战开发-仪表盘制作相关推荐

  1. pyqt 界面关闭信号_木辛老师的编程课堂之Python和Qt实战慕课软件开发:增加关闭按钮...

    软件实战开始,快速提供编程能力:通过实战,分析产品需求,梳理设计需求,提升项目分析和架构的能力.快点跟着木辛老师一起学习吧! 请点击右上角"关注"按钮关注我们哟:跟着木辛老师学习P ...

  2. 实战开发:新手小白如何用C++制作经典网游DNF

    十年前,那时候的网吧还不叫网咖,那时候没有王者荣耀也没有英雄联盟,那时候梦幻西游刚推出珍宝阁系统,那时候巫妖王的灵魂还封闭在冰封王座. 寻仙.穿越火线.征途.天龙八部--同时在线人数超百万的游戏纷纷涌 ...

  3. Qt及Qt Quick开发实战精解项目二俄罗斯方块 items方法报错

    在练习<Qt及Qt Quick开发实战精解>第二章的项目时,在MyView::clearFullRows中有这样一行代码 QList<QGraphicsItem*> list ...

  4. 迅为-i.MX6ULL开发板-QT实战项目DHT11网络编程实战练习(一)

    迅为-i.MX6ULL开发板-QT实战项目DHT11&网络编程实战练习(一) 发布时间:2021-7-2 09:49    发布者:落风 |编辑 文章目录1 项目前准备2 软件流程图3 Lin ...

  5. python嵌入式开发实战_嵌入式Qt实战教程 PDF 高清版

    给大家带来的一篇关于嵌入式相关的电子书资源,介绍了关于嵌入式.Qt实战方面的内容,本书是由电子工业出版社出版,格式为PDF,资源大小43.4 MB,陈志发,王苑增编写,目前豆瓣.亚马逊.当当.京东等电 ...

  6. 零基础学习嵌入式入门以及项目实战开发【手把手教+国内独家+原创】

    零基础学习嵌入式入门以及项目实战开发[手把手教+国内独家+原创] 独家拥有,绝对经典                            创 科 之 龙 嵌入式开发经典系列教程 [第一期] 主讲人: ...

  7. [嵌入式Linux项目实战开发]基于QT4.7.4的音乐播放器实现与设计【2018年给力项目】

    [嵌入式Linux项目实战开发]基于QT4.7.4的音乐播放器实现与设计[2018年给力项目]是[创科之龙]团队aiku嵌入式视频教程系列制作的现有的音乐播放器. 主要功能实现: 1.新建工程,基类选 ...

  8. Qt项目开发实例 (含源码)

    目录 1. QT开发环境安装以配置. 2. QT线段画板实战 3. 半小时玩转QT桌面系统托盘(含托盘消息) 4. QT入门开发一个时钟 5. 半小时教你做大转盘游戏(QT篇) 6. 手把手教你制作[ ...

  9. QT实战2:QWT的安装和使用(qwt6.1.4,win10,QT5.12.3)

    QT实战2:QWT的安装和使用攻略(qwt6.1.4,win10,QT5.12.3) QWT,即Qt Widgets for Technical Applications,是一个基于LGPL版权协议的 ...

最新文章

  1. java中decimalFormat格式化数值
  2. 【原】HTML页面元素加载顺序研究报告(2)----背景图片
  3. 金蝶清空日志数据库脚本
  4. 我的工具箱(不定期更新,欢迎跟帖推荐)
  5. 一些相当不错的php开源 AJAX聊天工具
  6. c语言标准输入输出ppt,c语言输入输出语句PPT
  7. cvCalcEMD2() 直方图匹配
  8. 深圳大学移动互联网应用期末大作业——垃圾分类app
  9. ActiveMQ下载安装使用教程
  10. 高斯消去法,列主元法,LU分解法python程序
  11. EpsonL360清零软件+清零方法
  12. python如何爬有道翻译_基于python爬取有道翻译过程图解
  13. 如何基于TAPD实践Scrum的敏捷开发?
  14. html关于圣诞节主题的网页,玩转圣诞创意!10个以圣诞节为主题的优秀网站设计...
  15. hr 标签可选的属性(续) 和 img 标签介绍
  16. 安装office2021时报错,无法卸载以前office版本残留项
  17. 汇率查询接口,免费实时货币汇率查询换算
  18. 战地3一直显示服务器断开连接,战地3一直Joining Server.解决办法_游侠网
  19. Sql 语句小课堂7:在sqlserver对多行数据实施随机数
  20. bat命令启动谷歌浏览器无痕模式

热门文章

  1. 爬虫训练场项目前端之 Bootstrap 信息提示框,按钮与按钮组,徽章,进度条
  2. 升级coda_Coda:从我们周围的结构中学习
  3. flex LCDS 整合 java 增删改查
  4. js判断当前设备及获取设备、浏览器的宽度和高度
  5. 一款运行在Mac平台上的浏览器:Vivaldi浏览器 for Mac
  6. windows下通过关键字批量删除远程k8s下deployment及pods
  7. (附源码)计算机毕业设计SSM金牛社区疫情防控系统
  8. Ubuntu22.04 VMWare Kernel Module Updater 失败
  9. 软件测试工程师面试一般常见问题汇总
  10. Python copy()与deepcopy()方法的区别