instrumentpanel.h
#ifndef INSTRUMENTPANEL_H#define INSTRUMENTPANEL_H#include <QWidget>#include <QTimer>namespace Ui {class InstrumentPanel;}class InstrumentPanel : public QWidget{Q_OBJECTpublic:explicit InstrumentPanel(QWidget *parent = 0);~InstrumentPanel();private:Ui::InstrumentPanel *ui;protected: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:QColor m_background;QColor m_foreground;int m_maxValue;int m_minValue;int m_startAngle;int m_endAngle;int m_scaleMajor;int m_scaleMinor;double m_value;int m_precision;QTimer *m_updateTimer;QString m_units;QString m_title;public Q_SLOTS:// void UpdateAngle();public:void UpdatePanelVal(double); // 用于外部设置仪表盘的值};#endif // INSTRUMENTPANEL_H
instrumentpanel.c
#include "instrumentpanel.h"#include "ui_instrumentpanel.h"#include <QPainter>InstrumentPanel::InstrumentPanel(QWidget *parent) :QWidget(parent),ui(new Ui::InstrumentPanel){ui->setupUi(this);// 8.构造函数的初始化m_background = Qt::black;m_foreground = Qt::green;m_startAngle = 60;m_endAngle = 60;m_scaleMajor = 10;m_minValue = -50;m_maxValue = 50;m_scaleMajor = 10;//分度m_scaleMinor = 10;m_units = "km/h";m_title = "Speed Meter";m_precision = 0;m_value = 0;m_updateTimer = new QTimer(this);m_updateTimer->setInterval(50);//间隔,微妙微单位,大家可以改一下这个值看看转动速度。// connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(UpdateAngle()));// m_updateTimer->start();//启动定时器setWindowFlags(Qt::FramelessWindowHint);//无窗体setAttribute(Qt::WA_TranslucentBackground);//背景透明resize(400, 400);}InstrumentPanel::~InstrumentPanel(){delete ui;}// 1.绘制表冠void InstrumentPanel::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(-radius, -radius, radius << 1, radius << 1);painter->setBrush(m_background = Qt::black);painter->drawEllipse(-92, -92, 184, 184);painter->restore();}// 2.绘制刻度值void InstrumentPanel::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();}// 3.绘制刻度线void InstrumentPanel::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();}// 4.绘制标题void InstrumentPanel::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();}// 5.显示的单位,与数值void InstrumentPanel::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);}// 6.绘制表针,和中心点void InstrumentPanel::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);}// 7.重绘函数void InstrumentPanel::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); /* 画表针 */}// 更新仪表盘void InstrumentPanel::UpdatePanelVal(double num){m_value = num;update();}
mainwindow.h
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include "instrumentpanel.h"namespace Ui {class MainWindow;}class MainWindow : public QMainWindow{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_pushButton_clicked();private:Ui::MainWindow *ui;private:InstrumentPanel *instrumentpanel1;InstrumentPanel *instrumentpanel2;InstrumentPanel *instrumentpanel3;};#endif // MAINWINDOW_H
mainwindow.c
#include "mainwindow.h"#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow){ui->setupUi(this);// 创建三个仪表盘类instrumentpanel1 = new InstrumentPanel(this);instrumentpanel2 = new InstrumentPanel(this);instrumentpanel3 = new InstrumentPanel(this);// 将三个仪表盘加载到窗口上ui->verticalLayout1->addWidget(instrumentpanel1);ui->verticalLayout2->addWidget(instrumentpanel2);ui->verticalLayout3->addWidget(instrumentpanel3);}MainWindow::~MainWindow(){delete ui;}void MainWindow::on_pushButton_clicked(){double num = ui->lineEdit->text().toDouble();instrumentpanel1->UpdatePanelVal(num);}
文件压缩包:ZG_Project.zip
参考资料:https://blog.csdn.net/Aidam_Bo/article/details/85266798
其他参考资料:
Qt编写自定义控件1-汽车仪表盘
Qt编写自定义控件21-圆弧仪表盘
