Qt实战开发-仪表盘制作
2017-02-13 22:01
751 查看
仪表盘制作
## 相关的基础知识 ##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()用于填充画笔所绘制的线条。
参考网址http://blog.csdn.net/zhang_xch/article/details/9051067
绘图的基本函数`
//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_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); public: void paintEvent(QPaintEvent *); }; #endif // WIDGET_H
上面的代码是能够绘画出图片的重要函数-重绘函数。只要出现以下几种情况,系统就会自动调用paintEvent方法。
a)当窗口部件第一次显示时,系统会自动产生一个绘图事件
b)重新调整窗口部件大小
c)当窗口部件被其他部件遮挡,然后又再次显示出来时,就会对隐藏的区域产生一个重绘事件
translate(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
e975
->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
include
**定时**
void Widget ::UpdateAngle()
{
m_value += 1;
if(m_value > 100)
{
m_value = 0;
}
update();//刷新控件,会调用paintEvent函数
}
**头文件**
ifndef MYSPEED_H
define MYSPEED_H
include
include
include
class Widget : public Widget{
Q_OBJECT
public:
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
相关文章推荐
- 实战tiny6410上的QT开发环境搭建与示例程序 作者:stephenzhu 小桥加加
- 【原创】CSS高效开发实战:CSS 3、LESS、SASS、Bootstrap、Foundation --读书笔记(5)使用放射渐变制作光影效果
- Qt实战之开发CSDN下载助手 (3)(结束篇)
- 响应式开发从原理到实战案例(二):制作没有响应式的静态页面
- 实战开发中UI资源制作标准
- 实战tiny6410上的QT开发环境搭建与示例程序
- Qt实战开发-CSDN登陆界面布局
- Qt实战之开发软件数据获取助手(eventFilter处理鼠标按下,event处理鼠标松开)
- iOS项目开发实战——制作视图的旋转动画
- QT开发实战精解
- 韩顺平主讲织梦dedecms 5.7二次开发实战仿站模板制作视频教程
- Qt实战之开发软件数据获取助手
- 实战微信JS SDK开发:贺卡制作与播放(2)
- Qt实战之开发CSDN下载助手 (2)
- iOS项目开发实战——制作视图的平移动画以及解决移动异常问题
- CSS高效开发实战:CSS 3、LESS、SASS、Bootstrap、Foundation --读书笔记(5)使用放射渐变制作光影效果
- 实战微信JS SDK开发:贺卡制作与播放(2)
- Qt实战之开发CSDN下载助手 (2)
- 使用Unity3D 自主实战开发的赛车游戏实例,关键点记录 (三)之UI菜单制作
- Qt实战开发-动态曲线图