QT QPainter 绘图
一、基本绘图类:
Qt 中提供了强大的 2D 绘图系统,可以使用相同的 API 在屏幕和绘图设备上进行绘制,它主要基于QPainter、QPaintDevice 和 QPaintEngine 这三个类。
- QPainter 用于执行绘图操作,其提供的 API 在 GUI 或 QImage、QOpenGLPaintDevice、QWidget 和QPaintDevice 显示图形(线、形状、渐变等)、文本和图像。
- QPaintDevice 不直接绘制物理显示画面,而利用逻辑界面的中间媒介。例如,绘制矩形图形时,为了将对象绘制到 QWidget、QGLPixelBuffer、QImage、QPixmap、QPicture 等多种界面中间,必须使用 QPaintDevice。
- QPaintEngine 提供了一些接口,可用于 QPainter 在不同的设备上进行绘制。
绘图系统由 QPainter 完成具体的绘制操作,QPainter 类提供了大量高度优化的函数来完成 GUI 编程所需要的大部分绘制工作。它可以绘制一切想要的图形,从最简单的一条直线到其他任何复杂的图形,例如:点、线、矩形、弧形、饼状图、多边形、贝塞尔弧线等。此外,QPainter 也支持一些高级特性,例如反走样(针对文字和图形边缘)、像素混合、渐变填充和矢量路径等,QPainter 也支持线性变换,例如平移、旋转、缩放。
QPainter 可以在继承自 QPaintDevice 类的任何对象上进行绘制操作。QPainter 也可以与 QPrinter 一起使用来打印文件和创建 PDF 文档。这意味着通常可以用相同的代码在屏幕上显示数据,也可以生成打印形式的报告。
QPainter 一般在部件的绘图事件 paintEvent() 中进行绘制,首先创建 QPainter 对象,然后进行图形的绘制,最后记得销毁 QPainter 对象。当窗口程序需要升级或者重新绘制时,调用此成员函数。使用 repaint()和 update() 后,调用函数 paintEvent()。
绘图事件:
void wiget::paintEvent(QPaintEvent *event)
{
}
QPainter只能在paintEvent中进行绘图。paintEvent事件在窗口刷新时触发,如最大化最小化,拖动窗口边缘时也会触发。
主要属性:
(1) QPen:控制线条颜色宽度线性。
(2) QBrush:设置一个区域的填充特性。
(3) QFont:用于绘制文字。
(4) QPixmap: 绘制图片,适合小图片。
(5) QImage: 绘制图片,适合大图片。
(6) QBitmap: QPixmap的一个子类,单通道图。
(7) QPicture: 一张画布,可以用于保存、读取Qpainter的绘图。
(8)QPrinter类是一个在打印机上绘制的绘图设备。它允许你将图形输出到打印机,生成打印预览,或者直接生成PDF文件。
基本图形绘制函数:
drawPoint() //画点
drawLine() //画直线
drawRect() //画矩形
drawArc() //画圆弧
drawEllipse() //画椭圆
drawPie() //画扇形
drawPolygon() //画多边形
drawChord() //画弦
drawRoundedRect() //画圆角矩形
drawPolyline() //画折线
drawConvexPolygon() //画凸多边形
二.重点绘图属性类介绍
1.QFont的一些属性与功能:
QFont是Qt框架中用于描述字体属性的工具类。
设置属性:
//设置属性:
void setFamily(const QString &family);
void setPointSize(int size);
void setWeight(int weight);
void setItalic(bool italic);
void setUnderline(bool underline);
获取属性:
//获取属性:
QString family() const;
int pointSize() const;
int weight() const;
bool italic() const;
bool underline() const;
2.QPen的一些属性与功能:
主要函数:
//函数原型 功能
void setColor(QColor &color) //设置画笔颜色
void setWidth(int width) //设置线条宽度
void setStyle(Qt::PenStyle style) //设置线条样式,参数为Qt::PenStyle枚举类型
void setCapStyle(Qt::PenCapStyle style) //设置线条端点样式,参数为Qt::PenCapStyle枚举类型
void setJoinStyle(Qt::PenJoinStyle style)//设置连接样式,参数为Qt::PenJoinStyle枚举类型属性修改后,需要使用setPen()来应用于绘图。
(1)线条样式:
void setStyle(Qt::PenStyle style) //设置线条样式,参数为Qt::PenStyle枚举类型
Qt::NoPen //没有画笔,设置此属性时,用画笔不会画出任何东西。但是画刷仍然有效,表现出来就是无边界,但有填充。
Qt::SolidLine //实线
Qt::DashLine //虚线
Qt::DotLine //点状线
Qt::DashDotLine //虚线和点交替
Qt::DashDotDotLine //虚线和双点交替
Qt::CustomDashLine //自定义样式
(2)线条端点样式:
void setCapStyle(Qt::PenCapStyle style) //设置线条端点样式,参数为Qt::PenCapStyle枚举类型
Qt::FlatCap //平顶端点
Qt::SquareCap //方形端点
Qt::RoundCap //圆形端点
(3)线条连接样式:
void setJoinStyle(Qt::PenJoinStyle style)//设置连接样式,参数为Qt::PenJoinStyle枚举类型属性修改后,需要使用setPen()来应用于绘图。
Qt::BevelJoin //斜切连接
Qt::MiterJoin //直角连接
Qt::RoundJoin //圆连接
3.QBrush的一些属性与功能:
主要函数:
//函数原型 功能
void setColor(QColor &color) //设置画刷颜色
void setStyle(Qt::BrushStyle style) //设置画刷样式
void setTexture(QPixmap &pixmap) //设置一个QPixmap图片作为画刷的图片
void setTextureImage(QImage &image) //设置一个QImage类型的图片作为画刷的图片
(1)基本填充和线性填充:
//枚举常量 描述
Qt::NoBrush //不填充
Qt::SolidPattern //单一颜色填充
Qt::HorPattern //水平线填充
Qt::VerPattern //垂直线填充
(2)渐变填充:
Qt::LinearGradientPattern //线性渐变,需要使用QLinearGradient类对象作为Brush
Qt::RadialGradientPattern //辐射渐变,需要使用QRadialGradient类对象作为Brush
Qt::ConicalGradientPattern //圆锥型渐变,需要使用QConicalGradient类对象作为Brush
Qt::TexturePattern //材质填充,需要指定texture或textureImage图片
4. QPrinter用法
(1)QPrinter printer;
printer.setOutputFormat(QPrinter::PdfFormat); // 设置输出格式为PDF,也可以其他格式
printer.setOutputFileName("output.pdf"); // 设置输出文件名
QPainter painter1(&printer);
painter1.drawText(100, 100, "Hello, PDF1!");
painter1.end(); // 结束绘制,内容将被发送到打印机
(2)注意:
用QPrinter需要添加 QT += printsupport;
当设置QPainter painter1(&printer)后,绘制图形输出到pdf文件,就不会再输出到ui页面上了。
sample8_123QPainter.h 文件
#pragma once
#include <QtWidgets/QWidget>
#include "ui_sample8_123QPainter.h"
class sample8_123QPainter : public QWidget
{
Q_OBJECT
public:
sample8_123QPainter(QWidget *parent = Q_NULLPTR);
private:
Ui::sample8_123QPainterClass ui;
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;//Q_DECL_OVERRIDE 表示这个函数是对父类虚函数的重载
void MyPaint1();//绘制矩形
void MyPaintText();//绘制文本
void MyPaintLine();//绘制直线
void MyPaintArc();//绘制弧线
void MyPaintEllipse();//绘制椭圆
void MyPaintPloygon();//绘制多边形
void MyPaintPicture();//绘制图片
void MyQLinearGradient();//线性渐变
void MyQRadialGradient();//径向渐变
};
sample8_123QPainter.cpp 文件
#include "sample8_123QPainter.h"
#include <QPainter>
sample8_123QPainter::sample8_123QPainter(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
setPalette(QPalette(Qt::white));//设置窗口为白色背景
setAutoFillBackground(true);
this->resize(400, 400);
}
void sample8_123QPainter::paintEvent(QPaintEvent *event)
{
//MyPaint1();//绘制矩形
MyPaintText();//绘制文本
}
绘制文本:
//绘制文本
void sample8_123QPainter::MyPaintText()
{
QPainter painter(this);
// 设置画笔颜色
painter.setPen(QColor(0, 160, 230));
// 设置字体:微软雅黑、点大小50、斜体
QFont font;
font.setFamily("Microsoft YaHei");
font.setPointSize(50);
font.setItalic(true);
painter.setFont(font);
// 绘制文本
painter.drawText(rect(), Qt::AlignCenter, "Qt");
}
创建一个 QPainter 对象,用于后面的绘制。使用 setPen() 来设置画笔的颜色(淡蓝色)。通过使用 QFont 来构建我们想要的字体,setFamily()设置字体为微软雅黑、setPointSize() 设置点大小30、setItalic() 设置斜体, 然后通过 setFont() 来设置字体,最后调用 drawText() 来实现文本的绘制,这里的 rect() 是指当前窗体的显示区域,Qt::AlignCenter 指文本居中绘制。
绘制矩形:
void sample8_123QPainter::MyPaint1()
{
QPainter painter(this);//创建QPainter对象
painter.setRenderHint(QPainter::Antialiasing);//
painter.setRenderHint(QPainter::TextAntialiasing);//
int W = this->width(); //绘图区宽度
int H = this->height();//绘图区高度
QRect rect(W / 4, H / 4, W / 2, H / 2);//中间区域矩形框
//设置画笔
QPen pen;
pen.setWidth(3);//线宽
pen.setColor(Qt::red);//划线颜色
//Qt::NoPen,Qt::SolidLine, Qt::DashLine, Qt::DotLine,Qt::DashDotLine,Qt::DashDotDotLine,Qt::CustomDashLine
pen.setStyle(Qt::DashLine);//线的类型,实线、虚线等
//Qt::FlatCap, Qt::SquareCap,Qt::RoundCap
pen.setCapStyle(Qt::FlatCap);//线端点样式
//Qt::MiterJoin,Qt::BevelJoin,Qt::RoundJoin,Qt::SvgMiterJoin
pen.setJoinStyle(Qt::BevelJoin);//线的连接点样式
painter.setPen(pen);
//设置画刷1
QBrush brush;
brush.setColor(Qt::yellow); //画刷颜色
brush.setStyle(Qt::SolidPattern); //画刷填充样式
painter.setBrush(brush);
设置画刷2
//QPixmap texturePixmap("../sample8_1QPainter/images/texture.jpg");//
//QBrush brush;
//brush.setStyle(Qt::TexturePattern);//画刷填充样式
//brush.setTexture(texturePixmap);//设置材质图片
//painter.setBrush(brush);
//绘图
//painter.drawLine(rect.left(),rect.top(),rect.right(),rect.bottom());
//painter.drawRect(rect);//只填充定义的渐变区域
//painter.drawRect(this->rect()); //填充更大区域,会有延展效果
//painter.fillRect(rect,Qt::red);//只填充定义的渐变区域,用红色填充
//painter.drawRoundRect(rect);//只填充定义的渐变区域,圆角矩形
painter.drawRoundedRect(rect,40,20);
}
使用 setPen() 来设置画笔颜色(淡蓝色)、宽度(2 像素),用来设置矩形区域的边框。然后使用setBrush() 来设置画刷颜色(橙色),用来填充矩形区域,最后调用 drawRect() 来实现矩形的绘制,其中参数依次顺序为 x、y、w、h,是指区域从 x 为 50,y 为 50 的坐标点起,宽度为 160,高度为 100 的矩形。
绘制直线:
//绘制直线
void sample8_123QPainter::MyPaintLine()
{
QPainter painter(this);
// 反走样
painter.setRenderHint(QPainter::Antialiasing, true);
// 设置画笔颜色
painter.setPen(QColor(0, 160, 230));
// 绘制直线
painter.drawLine(QPointF(0, height()), QPointF(width() / 2, height() / 2));
}
通过 setRenderHint() 来设置反走样,要么绘制出来的线条会出现锯齿,调用 setPen() 来设置画笔颜色(淡蓝色)。最后调用 drawLine() 来实现直线的绘制,其中 QPointF(0, height()) 是指直线的起点坐标、QPointF(width() / 2, height() / 2) 是指直线的终点坐标。
绘制弧线:
//绘制弧线
void sample8_123QPainter::MyPaintArc()
{
//矩形
QRectF rect(90.0, 90.0, 80.0, 90.0);
//起始角度
int startAngle = 30 * 16;
//跨越度数
int spanAngle = 120 * 16;
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
//设置画笔颜色、宽度
painter.setPen(QPen(QColor(0, 160, 230), 2));
//绘制弧线
painter.drawArc(rect, startAngle, spanAngle);
}
画弧线时,角度被分成了十六分之一,就是说,如果要 30 度,就需是 30*16。它有起始角度和跨度,还有位置矩形,所以,要想画出自己想要的弧线,就需要大概估算出各个参数的预估值。
绘制椭圆:
//绘制椭圆
void sample8_123QPainter::MyPaintEllipse()
{
QPainter painter(this);
//painter.setRenderHint(QPainter::Antialiasing, true);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::TextAntialiasing);
int W = this->width(); //绘图区宽度
int H = this->height();//绘图区高度
QRect rect(W / 4, H / 4, W / 2, H / 2);//中间区域矩形框
//设置画笔颜色、宽度
painter.setPen(QPen(QColor(0, 160, 230), 3));
//绘制椭圆
painter.drawEllipse(QPointF(120, 60), 50, 20);
//设置画刷颜色
painter.setBrush(QColor(255, 160, 90));
//绘制圆
painter.drawEllipse(QPointF(120, 140), 40, 40);
//设置画刷颜色
painter.setBrush(QColor(90, 160, 255));
painter.drawEllipse(rect);
}
绘制了一个椭圆和一个圆形,都是调用 drawEllipse() 接口,我们可以很轻易的发现,如果为椭圆的时候,后面两个参数不一样,圆形则相同。首先我们来看第一个参数 QPointF 是指椭圆的中心点相对当前窗体 QPoint(0, 0) 点的位置,后面的参数指椭圆的 x 轴及 y 轴的半径。
绘制多边形:
//绘制多边形
void sample8_123QPainter::MyPaintPloygon()
{
QPainter painter(this);
//反走样
painter.setRenderHint(QPainter::Antialiasing, true);
//设置画笔颜色
//painter.setPen(QColor(0, 160, 230));
//设置画笔颜色、宽度
painter.setPen(QPen(QColor(0, 160, 230), 3));
//各个点的坐标
static const QPointF points[4] = { QPointF(30, 40), QPointF(60, 150), QPointF(150, 160), QPointF(220, 100) };
//绘制多边形
painter.drawPolygon(points, 4);
}
绘制图片:
//绘制图片
void sample8_123QPainter::MyPaintPicture()
{
QPainter painter(this);
//反走样
painter.setRenderHint(QPainter::Antialiasing, true);
// 绘制图标
painter.drawPixmap(rect(), QPixmap("../sample8_1QPainter/images/001.jpg"));//
}
通过 drawPixmap() 来绘制图片,我们可以指定图片绘制的区域 QRect,这里为整个界面的区域,当界面伸缩的时候,图片也会跟着伸缩。
渐变绘制:
1、线性渐变
//线性渐变
void sample8_123QPainter::MyQLinearGradient()
{
QPainter painter(this);//创建QPainter对象
painter.setRenderHint(QPainter::Antialiasing);//
painter.setRenderHint(QPainter::TextAntialiasing);//
int W = this->width();//绘图区宽度
int H = this->height();//绘图区高度
QRect rect(W / 4, H / 4, W / 2, H / 2);//中间区域矩形框
//线性渐变
//QLinearGradient linearGrad(rect.left(),rect.top(),rect.right(),rect.bottom()); //对角线
QLinearGradient linearGrad(rect.left(), rect.top(), rect.right(), rect.top());//从左到右
linearGrad.setColorAt(0, Qt::blue);//起点颜色
linearGrad.setColorAt(0.5, Qt::green);//起点颜色
linearGrad.setColorAt(1, Qt::red);//终点颜色
linearGrad.setSpread(QGradient::ReflectSpread);//展布模式
//QGradient::PadSpread ,QGradient::RepeatSpread, QGradient::ReflectSpread
painter.setBrush(linearGrad);
//绘图
painter.drawRect(rect);//只填充定义的渐变区域
//painter.drawRect(this->rect());//填充更大区域,会有延展效果
}
//绘图
painter.drawRect(rect);//只填充定义的渐变区域
//painter.drawRect(this->rect());//填充更大区域,会有延展效果
//绘图
//painter.drawRect(rect);//只填充定义的渐变区域
painter.drawRect(this->rect());//填充更大区域,会有延展效果
2、径向渐变
//径向渐变
void sample8_123QPainter::MyQRadialGradient()
{
QPainter painter(this);//创建QPainter对象
painter.setRenderHint(QPainter::Antialiasing);//
painter.setRenderHint(QPainter::TextAntialiasing);//
int W = this->width();//绘图区宽度
int H = this->height();//绘图区高度
QRect rect(W / 4, H / 4, W / 2, H / 2);//中间区域矩形框
//径向渐变
QRadialGradient radialGrad(W / 2, H / 2, qMax(W / 8, H / 8), W / 2, H / 2);
//radialGrad.setColorAt(0,Qt::white);
radialGrad.setColorAt(0,Qt::green);
radialGrad.setColorAt(1,Qt::blue);
radialGrad.setSpread(QGradient::ReflectSpread);
//QGradient::PadSpread ,QGradient::RepeatSpread, QGradient::ReflectSpread
painter.setBrush(radialGrad);
//绘图
//painter.drawRect(rect);//只填充定义的渐变区域
painter.drawRect(this->rect());//填充更大区域,会有延展效果
}
3、圆锥形渐变
//圆锥型渐变
void sample8_123QPainter::MyQConicalGradient()
{
QPainter painter(this);//创建QPainter对象
painter.setRenderHint(QPainter::Antialiasing);//
painter.setRenderHint(QPainter::TextAntialiasing);//
int W = this->width();//绘图区宽度
int H = this->height();//绘图区高度
QRect rect(W / 4, H / 4, W / 2, H / 2);//中间区域矩形框
//圆锥型渐变
QConicalGradient coniGrad(W/2,H/2,45);
coniGrad.setColorAt(0,Qt::yellow);
coniGrad.setColorAt(0.5,Qt::blue);
coniGrad.setColorAt(1,Qt::green);
//coniGrad.setSpread(QGradient::PadSpread);//对于锥形渐变不起作用
painter.setBrush(coniGrad);
//绘图
painter.drawRect(rect);//只填充定义的渐变区域
//painter.drawRect(this->rect());//填充更大区域,会有延展效果
}