漂亮的表盘(自绘)
程序员文章站
2022-05-28 14:37:10
...
先看效果
这次用了二种方式实现的。一种是利用QPainter直接绘制的,一种是利用QPainterPath实现的。
头文件代码
#ifndef QDIALCOMPWIDGET_H
#define QDIALCOMPWIDGET_H
#include <QWidget>
#include <QPainter>
#include <QConicalGradient>
#include "qmath.h"
#define PI 3.12415926
//////////////////////////////////////////////////////////////////////////
//不支持指针颜色动态变化
//////////////////////////////////////////////////////////////////////////
class QDialCompWidget : public QWidget
{
Q_OBJECT
public:
QDialCompWidget(QWidget *parent = NULL);
~QDialCompWidget();
void setMaxValue(qreal max);
void setMinValue(qreal min);
void setValue(qreal value);
void setSuffix(QString sufstr); //后缀
private:
inline void initdata();
protected:
void paintEvent(QPaintEvent *e);
void drawRoundByPath(QPainter &painter); //利用QPainterPath 实现
void drawRoundByPainter(QPainter &painter); //利用QPainter实现
private:
QString m_sufstr;
qreal m_max;
qreal m_min;
qreal m_value;
QBrush m_oldbrush;
};
#endif // QDIALCOMPWIDGET_H
Cpp文件代码
#include "qdialcompwidget.h"
QDialCompWidget::QDialCompWidget(QWidget *parent)
: QWidget(parent)
{
initdata();
}
QDialCompWidget::~QDialCompWidget()
{
}
void QDialCompWidget::initdata()
{
m_max = 100;
m_min = 0;
m_value = 0;
}
void QDialCompWidget::setMaxValue( qreal max )
{
m_max = max;
update();
}
void QDialCompWidget::setMinValue( qreal min )
{
m_min = min;
update();
}
void QDialCompWidget::setValue( qreal value )
{
m_value = value;
update();
}
void QDialCompWidget::setSuffix( QString sufstr )
{
m_sufstr = sufstr;
update();
}
void QDialCompWidget::paintEvent( QPaintEvent *e )
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
m_oldbrush = painter.background();
//drawRoundByPainter(painter);
drawRoundByPath(painter);
}
void QDialCompWidget::drawRoundByPainter( QPainter &painter )
{
int w = width();
int h = height();
qreal randius= qMin(w*0.8/2,h*0.8/2);
int setp = randius*0.08;
qreal outrandius = randius + setp;
qreal inrandius = randius - setp;
QPointF certp(w/2,h/2);
qreal startAngle = -60*16;
qreal spanAngle = 300*16;
qreal angele = 30;
qreal lw,lh;
lw = outrandius*qSin(PI/6);
lh = outrandius*qCos(PI/6);
QPointF outleftp(certp.x()-lw,certp.y()+lh);
QPointF outrigth(certp.x()+lw,certp.y()+lh);
QRectF outrectangle(certp.x()-outrandius, certp.y()-outrandius, outrandius*2, outrandius*2);
//背景色
painter.save();
painter.setBrush(m_oldbrush);
painter.drawEllipse(outrectangle);
painter.restore();
//外圆
painter.save();
QConicalGradient congradient(outrectangle.center(),245);
congradient.setColorAt(0,QColor("#EC0000")); //红色
congradient.setColorAt(0.5,QColor("#E5D317"));
congradient.setColorAt(1,QColor("#2BB52C")); //绿色
painter.setBrush(congradient);
painter.drawPie(outrectangle, startAngle, spanAngle);
painter.restore();
//内圆
lw = inrandius*qSin(PI/6);
lh = inrandius*qCos(PI/6);
QPointF inleftp(certp.x()-lw,certp.y()+lh);
QPointF inrigth(certp.x()+lw,certp.y()+lh);
painter.save();
QRectF inrectangle(certp.x()-inrandius, certp.y()-inrandius, inrandius*2, inrandius*2);
painter.drawPie(inrectangle,startAngle,spanAngle);
painter.restore();
painter.save();
painter.setBrush(congradient);
//左侧半小圆
qreal tmph =(outleftp.y()-inleftp.y())/2;
qreal tmpw =(outleftp.x()-inleftp.x())/2;
QPointF tp(outleftp.x()-tmpw,outleftp.y()-tmph);
QRectF rmprect(tp.x()-setp,tp.y()-setp,setp*2,setp*2);
painter.drawChord(rmprect,-130*16,200*16); //角度大小取决于 angele ,跨度200级以上(防止放大有小白条)
//右侧半小圆
tmph =(outrigth.y()-inrigth.y())/2;
tmpw =(outrigth.x()-inrigth.x())/2;
QPointF righttp(outrigth.x()-tmpw,outrigth.y()-tmph);
QRectF rmrightrect(righttp.x()-setp,righttp.y()-setp,setp*2,setp*2);
painter.drawChord(rmrightrect,110*16,200*16); //角度大小取决于 angele,跨度200级以上(防止放大有小白条)
painter.restore();
//中间部分 白色填充
painter.save();
painter.setBrush(/*Qt::white*/m_oldbrush);
painter.drawEllipse(inrectangle);
painter.restore();
//里侧圆
painter.save();
qreal inirandius = inrandius*0.9;
QPainterPath path;
QRectF inirect(certp.x()-inirandius,certp.y()-inirandius,inirandius*2,inirandius*2);
QRadialGradient radialgradient(inirect.center(),inirandius);
QColor color_1("#2BB52C"); //绿色
QColor color_2("#2BB52C");
QColor color_3("#2BB52C");
color_1.setAlpha(200);
color_2.setAlpha(100);
color_3.setAlpha(20);
radialgradient.setColorAt(0.95,color_1); //
radialgradient.setColorAt(0.99,color_2);
radialgradient.setColorAt(1,color_3);
painter.setBrush(radialgradient);
path.addEllipse(inirect);
painter.drawPath(path);
painter.restore();
painter.save();
painter.setBrush(/*Qt::white*/m_oldbrush);
inirandius *= 0.97;
QRectF tmprect(certp.x()-inirandius,certp.y()-inirandius,inirandius*2,inirandius*2);
painter.drawEllipse(tmprect);
painter.restore();
//值value
painter.save();
QPen textpen;
textpen.setColor("black");
QFont f;
f.setPixelSize(inirandius/2);
painter.setPen(textpen);
painter.setFont(f);
painter.drawText(tmprect,Qt::AlignCenter,QString("%1%2").arg(m_value).arg(m_sufstr));
painter.restore();
//最大最小值
painter.save();
QFont f2;
f2.setPixelSize(inirandius/4);
painter.setPen(textpen);
painter.setFont(f2);
QRectF minrect(outleftp.x(),h*0.9,randius,randius*0.2);
QRectF maxrect(certp.x()+inirandius/2,h*0.9,randius,randius*0.2);
painter.drawText(minrect,QString("%1").arg(m_min));
painter.drawText(maxrect,QString("%1").arg(m_max));
painter.restore();
//指针
setp = 30+1.0*m_value*(360-55)/(m_max-m_min); //占用300度不是360
painter.save();
QTransform t;
t.translate(certp.x(),certp.y());
t.rotate(setp);
painter.setTransform(t);
//QRectF rectcongradient2(-inirandius,-inirandius,inirandius*2,inirandius*2);
//QConicalGradient congradient2(rectcongradient2.center(),360);
////congradient2.setAngle(-240+setp-30);
//congradient2.setColorAt(0,QColor("#EC0000")); //红色
//congradient2.setColorAt(0.5,QColor("#E5D317"));
//congradient2.setColorAt(1.0,QColor("#2BB52C")); //绿色
//painter.setBrush(congradient2);
QRectF maxrect22(0,inirandius*0.88,5,inirandius*0.1);
painter.setBrush(/*Qt::red*/congradient);
painter.drawRoundedRect(maxrect22,5,5);
painter.restore();
}
void QDialCompWidget::drawRoundByPath( QPainter &painter )
{
int w = width();
int h = height();
qreal randius= qMin(w*0.8/2,h*0.8/2);
int setp = randius*0.08;
qreal outrandius = randius + setp;
qreal inrandius = randius - setp;
QPointF certp(w/2,h/2);
qreal startAngle = -60;
qreal spanAngle = 300;
qreal angele = 30;
painter.save();
//内圆
qreal lw = inrandius*qSin(PI/6);
qreal lh = inrandius*qCos(PI/6);
QPointF inleftp(certp.x()-lw,certp.y()+lh);
QPointF inrigth(certp.x()+lw,certp.y()+lh);
QRectF rectangle(certp.x()-inrandius, certp.y()-inrandius, inrandius*2, inrandius*2);
QPainterPath path;
path.moveTo(inleftp);
path.arcTo(rectangle, startAngle, spanAngle);
//外圆
lw = outrandius*qSin(PI/6);
lh = outrandius*qCos(PI/6);
QPointF outleftp(certp.x()-lw,certp.y()+lh);
QPointF outrigth(certp.x()+lw,certp.y()+lh);
path.moveTo(outleftp);
QRectF rectangle2(certp.x()-outrandius, certp.y()-outrandius, outrandius*2, outrandius*2);
path.arcTo(rectangle2, startAngle, spanAngle);
QConicalGradient congradient(rectangle2.center(),250);
congradient.setColorAt(0,QColor("#EC0000")); //红色
congradient.setColorAt(0.5,QColor("#E5D317"));
congradient.setColorAt(1,QColor("#2BB52C")); //绿色
painter.setBrush(congradient);
painter.drawPath(path);
painter.eraseRect(inleftp.x(),inleftp.y()-1,inrigth.x()-inleftp.x(),outleftp.y()-inleftp.y()+20);
QPainterPath leftpath;
//左侧小圆
leftpath.moveTo(outleftp);
qreal tmph =(outleftp.y()-inleftp.y())/2;
qreal tmpw =(outleftp.x()-inleftp.x())/2;
QPointF tp(outleftp.x()-tmpw,outleftp.y()-tmph);
QRectF rmprect(tp.x()-setp,tp.y()-setp,setp*2,setp*2);
leftpath.arcTo(rmprect,-110,200); //角度大小取决于 angele
//painter.setBrush(congradient);
painter.drawPath(leftpath);
QPainterPath rightpath;
//右侧小圆
rightpath.moveTo(outrigth);
tmph =(outrigth.y()-inrigth.y())/2;
tmpw =(outrigth.x()-inrigth.x())/2;
QPointF righttp(outrigth.x()-tmpw,outrigth.y()-tmph);
QRectF rmrightrect(righttp.x()-setp,righttp.y()-setp,setp*2,setp*2);
rightpath.arcTo(rmrightrect,110,200); //角度大小取决于 angele
//painter.setBrush(congradient);
painter.drawPath(rightpath);
painter.restore();
//中间部分 白色填充
painter.save();
painter.setBrush(/*Qt::white*/m_oldbrush);
painter.drawEllipse(rectangle);
painter.restore();
//里侧圆
painter.save();
qreal inirandius = inrandius*0.9;
QPainterPath inipath;
QRectF inirect(certp.x()-inirandius,certp.y()-inirandius,inirandius*2,inirandius*2);
QRadialGradient radialgradient(inirect.center(),inirandius);
QColor color_1("#2BB52C"); //绿色
QColor color_2("#2BB52C");
QColor color_3("#2BB52C");
color_1.setAlpha(200);
color_2.setAlpha(100);
color_3.setAlpha(20);
radialgradient.setColorAt(0.95,color_1); //
radialgradient.setColorAt(0.99,color_2);
radialgradient.setColorAt(1,color_3);
painter.setBrush(radialgradient);
inipath.addEllipse(inirect);
painter.drawPath(inipath);
painter.restore();
painter.save();
painter.setBrush(/*Qt::white*/m_oldbrush);
inirandius *= 0.97;
QRectF tmprect(certp.x()-inirandius,certp.y()-inirandius,inirandius*2,inirandius*2);
painter.drawEllipse(tmprect);
painter.restore();
//值value
painter.save();
QPen textpen;
textpen.setColor("black");
QFont f;
f.setPixelSize(inirandius/2);
painter.setPen(textpen);
painter.setFont(f);
painter.drawText(tmprect,Qt::AlignCenter,QString("%1%2").arg(m_value).arg(m_sufstr));
painter.restore();
//最大最小值
painter.save();
QFont f2;
f2.setPixelSize(inirandius/4);
painter.setPen(textpen);
painter.setFont(f2);
QRectF minrect(outleftp.x(),h*0.9,randius,randius*0.2);
QRectF maxrect(certp.x()+inirandius/2,h*0.9,randius,randius*0.2);
painter.drawText(minrect,QString("%1").arg(m_min));
painter.drawText(maxrect,QString("%1").arg(m_max));
painter.restore();
//指针
setp = 30+1.0*m_value*(360-60)/(m_max-m_min); //占用300度不是360
painter.save();
QTransform t;
t.translate(certp.x(),certp.y());
t.rotate(setp);
painter.setTransform(t);
QRectF maxrect22(0,inirandius*0.88,5,inirandius*0.1);
painter.setBrush(/*Qt::red*/congradient);
painter.drawRoundedRect(maxrect22,5,5);
painter.restore();
}