QT-QPainter
- 1.QPainter画图
- 1.1 概述
- 1.1 QPainter设置
- 1.2 QPainter画线
- 1.3 QPainter画矩形
- 1.4 QPainter画圆
- 1.5 QPainter画圆弧
- 1.6 QPainter画扇形
- 2.QGradient
- 2.1 QLinearGradient线性渐变
- 2.2 QRadialGradient径向渐变
- 2.3 QConicalGradient锥形渐变
- 3.综合仿雷达
- 4.仪表盘
- 4.1初
- 4.2 正弦纠正刻度文字方向
- 4.3 终
1.QPainter画图
1.1 概述
坐标系为
QPainter是Qt 库中用于在屏幕上进行绘画的类。它提供了各种绘制功能,比如画线、画图形、画文本等。
在使用QPainter之前,需要对QPaintEvent事件进行重写
1.1 QPainter设置
1.初始化
QPainter painter(this);
2.设置笔刷
QPen pen(Qt::blue,7);
painter.setPen(pen);
painter.setRenderHints(QPainter::Antialiasing,true); //抗锯齿
painter.setFont(QFont("Arial", 30));
1.2 QPainter画线
//画线-两点确定
painter.drawLine(10,200,300,20);
painter.drawLine(QLine(10,200,300,20));
painter.drawLine(QPoint(10,200),QPoint(300,20));
1.3 QPainter画矩形
//画矩形
// void drawRect(const QRectF &rectangle) QRectF浮点型
QRect rectangle(20,100,200,100);
painter.drawRect(rectangle);
// void drawRect(int x, int y, int width, int height)
painter.drawRect(20,100,200,100);
// void drawRect(const QRect &rectangle)
1.4 QPainter画圆
//画圆形--在矩形区域画椭圆
painter.drawEllipse(rectangle);
painter.drawEllipse(rect().center(),200,100); //在整个窗口的中间,画一个宽200 高100的椭圆
painter.drawEllipse(QPoint(80,500),80,80); //在yuan圆心的坐标点为(80,500)处画一个80*80的圆
1.5 QPainter画圆弧
绘制的弧由给定的矩形、起始角和伸缩脚定义。
起始角和伸缩脚必须以1/16度表示,即一个完整的圆等于5760(16*360)。角的正值表示逆时针方向,角的负值表示顺时针方向
零度在3点钟的位置。
如:
//(x,y,width,height)--x,y为左上角起始点坐标
QRect rectangle(200,100,200,150);
painter.drawRect(rectangle);
painter.drawArc(rectangle,30*16,120*16);
//30 起始角,正值逆时针方向,负值顺时针方向
//120 伸缩角
QRect rectangle(200,100,200,150);
painter.drawRect(rectangle);
painter.drawArc(rectangle,30*16,120*16);
painter.drawArc(30,100,100,180,45*16,90*16);
1.6 QPainter画扇形
painter.drawPie(rectangle,30*16,120*16);
2.QGradient
QLinearGradient(const QPointF &start, const QPointF &finalStop)//渐变色起始点和终止点
setColorAt(qreal position, const QColor &color)
2.1 QLinearGradient线性渐变
QPainter painter(this);
//起始点宽的 x:1/3---2/3 y:1/2处
QLinearGradient lineGradient(width()/3,height()/2,width()*2/3,height()/2);
lineGradient.setColorAt(0.1,Qt::black); //用给定的颜色在给定的位置创建一个停止点,给定的位置必须在0到1之间。
lineGradient.setColorAt(1,Qt::white);
QBrush brush(lineGradient);
painter.setBrush(brush);
painter.drawRect(rect());
QPainter painter(this);
//从左上角到右下角开始变
QLinearGradient lineGradient(0,0,width(),height());
lineGradient.setColorAt(0.1,Qt::black);
lineGradient.setColorAt(1,Qt::white);
QBrush brush(lineGradient);
painter.setBrush(brush);
painter.drawRect(rect());
QPainter painter(this);
QLinearGradient lineGradient(0,0,width(),height());
lineGradient.setColorAt(0.7,Qt::black);
lineGradient.setColorAt(1,Qt::white);
QBrush brush(lineGradient);
painter.setBrush(brush);
painter.drawRect(rect());
}
lineGradient.setColorAt(0,Qt::blue);
lineGradient.setColorAt(0.4,Qt::red);
lineGradient.setColorAt(0.7,Qt::black);
lineGradient.setColorAt(1,Qt::white);
0-0.4 :蓝红渐变
0.4-0.7 :红黑渐变
0.7-1 :黑白渐变
2.2 QRadialGradient径向渐变
//QRadialGradient(const QPointF ¢er, qreal radius, const QPointF &focalPoint)
QPainter painter(this);
QRadialGradient radialGradient(400,400,100); //400,400--中心点,100辐射半径
radialGradient.setColorAt(0,Qt::white); //中心
radialGradient.setColorAt(1,Qt::black); //边缘
painter.setBrush(QBrush(radialGradient));
painter.drawRect(200,300,400,200);
2.3 QConicalGradient锥形渐变
QPainter painter(this);
QConicalGradient conicalGradient(400,400,0);
// 添加颜色停靠点
conicalGradient.setColorAt(0.0, Qt::red);
conicalGradient.setColorAt(0.5, Qt::blue);
conicalGradient.setColorAt(1.0, Qt::red);
// 使用这个渐变创建 QBrush
QBrush brush(conicalGradient);
// 使用 QBrush 进行绘图
painter.setPen(Qt::NoPen); //设置无边框
painter.setBrush(brush);
painter.drawRect(200,300,400,200);
3.综合仿雷达
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timer = new QTimer(this);
connect(timer,&QTimer::timeout,this,[=](){
startAngle += 30;
if(startAngle >= 360){
startAngle = 0;
}
update();
});
timer->setInterval(100);
timer->start();
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true); //平滑处理
painter.setBrush(QBrush(Qt::black));
painter.drawRect(rect()); //设置背景色被黑色
painter.setBrush(Qt::NoBrush);
painter.translate(rect().center()); //将坐标点转移到中间位置
int rEve = height()/2/7;
int dataTmp = rEve * 7;
QPen pen(Qt::green,4); //设置画笔
painter.setPen(pen);
for(int i=1;i<=7;i++){
painter.drawEllipse(QPoint(0,0),rEve*i,rEve*i);
}
painter.drawLine(-rEve*7,0,rEve*7,0); //横线
painter.drawLine(0,-rEve*7,0,rEve*7); //竖线
QConicalGradient conGradient(0,0,-startAngle); //中心点(0,0)起始角度30
//设置锥形渐变色
conGradient.setColorAt(0,QColor(0,255,0,200));
conGradient.setColorAt(0.1,QColor(0,255,0,100));
conGradient.setColorAt(0.2,QColor(0,255,0,0));
conGradient.setColorAt(1,QColor(0,255,0,0));
//用渐变色指定画刷
painter.setBrush(conGradient);
painter.setPen(Qt::NoPen); //取消边框
//画扇形
painter.drawPie(QRect(-dataTmp,-dataTmp,2*dataTmp,2*dataTmp),-startAngle*16,70*16);
}
4.仪表盘
4.1初
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timer = new QTimer(this);
currentValue = 0;
connect(timer,&QTimer::timeout,[=](){
if(mark == 0){
currentValue++;
if(currentValue >= 60){
mark = 1;
}
}
if(mark == 1){
currentValue--;
if(currentValue == 0){
mark = 0;
}
}
update();
});
timer->start(50);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
//底色弄成黑色
painter.setBrush(QBrush(Qt::black));
painter.drawRect(rect());
//坐标系平移到中心
painter.translate(rect().center());
//画大圆
painter.drawEllipse(QPoint(0,0),height()/2,height()/2);
painter.setBrush(Qt::NoBrush);
//画小圆
painter.setPen(QPen(Qt::white,3));
painter.drawEllipse(QPoint(0,0),60,60);
//当前值
painter.setFont(QFont("华文宋体",10));
painter.drawText(QRect(-60,-60,120,120),Qt::AlignCenter,QString::number(currentValue));
//画刻度-旋转坐标轴画线
//1.算出一个刻度需要旋转的角度
double angle = 240.0 / 60.0;
//2.设置第一个刻度的位置
//顺时针旋转坐标轴到15度,会一直处在15度位置直到下一次旋转将在15基础上+再次旋转的角度
painter.setFont(QFont("华文宋体",10));
painter.save(); //保存旋转前的位置
painter.rotate(150);
for(int i = 0;i<=60;i++){
if(i%5 == 0){
//画字
if(135+angle * i < 270){
painter.rotate(180);
painter.drawText(-(height()/2-30),10,QString::number(i*4));
painter.rotate(-180);
}else{
painter.drawText(height()/2-70,10,QString::number(i*4));
}
//画长刻度
painter.drawLine(height()/2-20,0,height()/2-3,0);
}else{ //画短刻度
painter.drawLine(height()/2-8,0,height()/2-3,0);
}
//画完后旋转
painter.rotate(angle);
}
//画指针-线
//坐标轴先回到原点
painter.restore(); //恢复到原来位置
painter.save();
painter.rotate(150+ angle *currentValue);
painter.drawLine(60,0,height()/2-50-20,0);
//画扇形
painter.restore();
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(255,0,0,150));
painter.drawPie(QRect(-height()/2,-height()/2,height(),height()),(360-150)*16,-angle*currentValue*16);//angle前取负数,为了让它顺时针方向画
}
4.2 正弦纠正刻度文字方向
1.如图下,
红框中50所示,刻度线处的文字应当保持与50同样的方向而不是图中120的方向
易知在不改变坐标系的情况下无理论怎么旋转,其在远处所写的字符都无法达到红框50所显示的字符
易知通过50代替120可知,若将坐标系原点移到120处在修改字符50为120即可
所以对于120的修改只需要在此坐标系的基础上将y轴的坐标改到120的坐标处即可
2.那么它地方的坐标如何得到呢?
已知条件
1.圆的半径 r
2.圆的偏转角度 a
所以可得x,y的坐标
x = r * cosa;
y = r * sina;
//写刻度文字
int r = height()/2- 45;
for(int i=0;i<=60;i++){
if(i%5 == 0){
//保存坐标系
painter.save();
//算出平移点
int delX = qCos(qDegreesToRadians(210-angle*i)) * r;
int delY = qSin(qDegreesToRadians(210-angle*i)) * r;
//平移坐标系
painter.translate(QPoint(delX,-delY));
//旋转坐标系
//painter.rotate(angle * i); //已知120是正好的
//写上文字
painter.drawText(-20,-20,50,30, Qt::AlignCenter,QString::number(i*4));
//恢复坐标系
painter.restore();
}
}
通过以上的修改,可将刻度转换成如下,但是只有120是正好的,其他的刻度需要先将坐标系旋转才能达到120的效果
3.已知angle = 240.0 / 60.0 = 4
在120处旋转角为0,所以其他位置的旋转角度只需要凑齐120度的旋转角度即可
120刻度时旋转角度为0,已知,在120时 angle * i = 120,若想在此处旋转角度为0
则:
0 = angle * i - 120;
所以其他位置应当旋转的角度为
painter.rotate(angle * i - 120);
int r = height()/2- 50;
for(int i=0;i<=60;i++){
if(i%5 == 0){
//保存坐标系
painter.save();
//算出平移点
int delX = qCos(qDegreesToRadians(210-angle*i)) * r; //qt中认得是弧度,弧度=角度*pi/180
int delY = qSin(qDegreesToRadians(210-angle*i)) * r;
//平移坐标系
painter.translate(QPoint(delX,-delY));
//旋转坐标系
painter.rotate(angle * i - 120);
//写上文字
painter.drawText(-25,-25,50,30, Qt::AlignCenter,QString::number(i*4));
//恢复坐标系
painter.restore();
}
}
4.3 终
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QtMath>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setFixedSize(800,600); //设置默认窗口
startAngle = 150;
startSpeed();
}
Widget::~Widget()
{
delete ui;
}
void Widget::initCanvas(QPainter& painter)
{
painter.setRenderHint(QPainter::Antialiasing,true);
//底色弄成黑色
painter.setBrush(QBrush(Qt::black));
painter.drawRect(rect());
//坐标系平移到中心
painter.translate(rect().center().x(),rect().center().y()+50);
}
void Widget::drawMiddleCircle(QPainter &painter, int radius)
{
//画小圆
painter.setPen(QPen(Qt::white,3));
painter.drawEllipse(QPoint(0,0),radius,radius);
}
void Widget::drawCurrentSpeed(QPainter &painter)
{
//当前值
painter.setPen(Qt::white);
QFont font("Arial",18);
font.setBold(true); //加粗
painter.setFont(font);
painter.drawText(QRect(-60,-60,120,70),Qt::AlignCenter,QString::number(currentValue*4));
QFont font2("Arial",10);
font2.setBold(true); //加粗
painter.setFont(font2);
painter.drawText(QRect(-60,-60,120,160),Qt::AlignCenter,"Km/h");
}
void Widget::drawScale(QPainter &painter,int radius)
{
//1.算出一个刻度需要旋转的角度
angle = 240.0 / 60.0;
//2.设置第一个刻度的位置
//顺时针旋转坐标轴到15度,会一直处在15度位置直到下一次旋转将在15基础上+再次旋转的角度
painter.save(); //保存旋转前的位置
painter.setPen(QPen(Qt::white,5));
painter.rotate(startAngle);
for(int i = 0;i<=60;i++){
if(i>=40){
painter.setPen(QPen(Qt::red,5));
}
if(i%5 == 0){
//画长刻度
painter.drawLine(radius-20,0,radius-3,0);
}else{ //画短刻度
painter.drawLine(radius-8,0,radius-3,0);
}
//画完后旋转
painter.rotate(angle);
}
painter.restore();
painter.setPen(QPen(Qt::white,5));
}
void Widget::drawScaleText(QPainter &painter,int radius)
{
QFont font("Arial",10);
font.setBold(true); //加粗
painter.setFont(font);
int r = radius - 50;
for(int i=0;i<=60;i++){
if(i%5 == 0){
//保存坐标系
painter.save();
//算出平移点
int delX = qCos(qDegreesToRadians(210-angle*i)) * r; //qt中认得是弧度,弧度=角度*pi/180
int delY = qSin(qDegreesToRadians(210-angle*i)) * r;
//平移坐标系
painter.translate(QPoint(delX,-delY));
//旋转坐标系
painter.rotate(angle * i - 120);
//写上文字
painter.drawText(-25,-25,50,30, Qt::AlignCenter,QString::number(i*4));
//恢复坐标系
painter.restore();
}
}
}
void Widget::drawPointLine(QPainter &painter,int length)
{
//坐标轴先回到原点
painter.save();
painter.setBrush(Qt::white);
painter.setPen(Qt::NoPen);
static const QPointF points[4] = {
QPointF(0,0),
QPointF(200,-1.0),
QPointF(200.0,1.0),
QPointF(0.0,15.0),
};
painter.rotate(startAngle + angle *currentValue);
painter.drawPolygon(points,4);
// painter.drawLine(60,0,length,0);
painter.restore(); //恢复到原来位置
}
void Widget::drawSpeedPie(QPainter &painter, int radius)
{
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(255,0,0,80));
painter.drawPie(QRect(-radius,-radius,radius*2,radius*2),(360-startAngle)*16,-angle*currentValue*16);//angle前取负数,为了让它顺时针方向画
}
void Widget::startSpeed()
{
timer = new QTimer(this);
currentValue = 0;
connect(timer,&QTimer::timeout,[=](){
if(mark == 0){
currentValue++;
if(currentValue >= 61){
mark = 1;
}
}
if(mark == 1){
currentValue--;
if(currentValue == 0){
mark = 0;
}
}
update(); //更新
});
timer->start(50);
}
void Widget::drawEllipseInnerBlack(QPainter &painter, int radius)
{
painter.setBrush(Qt::black);
painter.drawEllipse(QPoint(0,0),radius,radius);
}
void Widget::drawEllipseInnerShine(QPainter &painter, int radius)
{
QRadialGradient radialGradient(0,0,radius);
radialGradient.setColorAt(0,QColor(255,0,0,200));
radialGradient.setColorAt(1,QColor(0,0,0,100));
painter.setBrush(radialGradient);
painter.drawEllipse(QPoint(0,0),radius,radius);
}
void Widget::drawEllipseOuterShine(QPainter &painter, int radius)
{
painter.setPen(Qt::NoPen);
QRadialGradient radialGradient(0,0,radius);
radialGradient.setColorAt(1,QColor(255,0,0,200));
radialGradient.setColorAt(0.97,QColor(255,0,0,120));
radialGradient.setColorAt(0.9,QColor(0,0,0,0));
radialGradient.setColorAt(0,QColor(0,0,0,0));
painter.setBrush(radialGradient);
painter.drawPie(QRect(-radius,-radius,radius*2,radius*2),(360-150)*16,-angle*61*16);//angle前取负数,为了让它顺时针方向画
}
void Widget::drawLogo(QPainter &painter, int radius)
{
QRect rectangle(-40,radius*0.38,80,80);
painter.drawPixmap(rectangle,QPixmap(":/icon.png"));
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
int rad = height()/2;
//初始化画布
initCanvas(painter);
//画小圆
drawMiddleCircle(painter,60);
//画刻度-旋转坐标轴画线
drawScale(painter,rad);
//写刻度文字
drawScaleText(painter,rad);
//画指针-线
drawPointLine(painter,rad-70);
//画扇形
drawSpeedPie(painter,rad+22);
//画渐变色内圈圆
drawEllipseInnerShine(painter,110);
//画黑色内圈
drawEllipseInnerBlack(painter,80);
//画当前速度
drawCurrentSpeed(painter);
//画外环发光圈
drawEllipseOuterShine(painter,rad+22);
drawLogo(painter,rad);
}
链接:https://pan.baidu.com/s/1UFuGa5WBCZv0H1BtSsIJbw
提取码:14wi
--来自百度网盘超级会员V5的分享