绘图
QPainter
QPainter
是 Qt 框架中的一个类,用于在各种设备上绘制图形和文本。它是一个低级的绘图接口,提供了丰富的方法来绘制线条、形状、文本和图像等。QPainter
通常与 QWidget
或其子类一起使用,但也可以用于绘制到其他类型的设备上,QPainter
可以在继承QPaintDevice
类的任何对象进行操作。
QPainter
的常见用法是在小部件的绘画事件中:构造和自定义(例如设置笔或画笔)painter,然后画画。
isActive()
函数指示画家是否处于活动状态。画家由begin()
函数和接受QPaintDevice
参数的构造函数激活。end()
函数和析构函数将其停用。
以下是使用 QPainter
的一些基本步骤:
-
创建 QPainter 对象: 创建一个
QPainter
对象需要一个目标设备上下文(如QWidget
或QImage
)作为参数。QPainter::QPainter(QPaintDevice *device)
QPainter painter(this); // 假设当前对象是一个QWidget的子类
-
设置画笔和画刷: 使用
QPainter
的setPen()
和setBrush()
方法来设置绘制时使用的画笔和画刷。painter.setPen(QPen(Qt::black, 2)); // 设置画笔为黑色,宽度为2 painter.setBrush(QBrush(Qt::blue)); // 设置画刷为蓝色
-
绘制图形: 使用
QPainter
的绘图方法来绘制线条、矩形、圆形等。painter.drawLine(10, 10, 100, 100); // 绘制一条从(10, 10)到(100, 100)的线 painter.drawRect(50, 50, 100, 100); // 绘制一个矩形 painter.drawEllipse(150, 150, 50, 50); // 绘制一个椭圆
-
绘制文本: 使用
QPainter
的drawText()
方法来绘制文本。painter.drawText(200, 200, "Hello, Qt!");
-
绘制图像: 使用
QPainter
的drawImage()
方法来绘制图像。QImage image("path/to/image.png"); painter.drawImage(250, 250, image);
-
结束绘制: 完成绘制后,不需要手动销毁
QPainter
对象,因为它会自动在作用域结束时被销毁。
使用 QPainter
时,需要注意以下几点:
-
绘制操作应在
QPainter
对象的作用域内完成,以确保资源正确释放。 -
绘制操作是不可变的,即绘制完成后不能撤销。
-
绘制操作是依赖于设备的,不同的设备可能有不同的性能表现。
QPainter
是 Qt 中进行自定义绘图的强大工具,适用于需要精细控制绘制过程的场合。
7.实例
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
//The common use of QPainter is inside a widget's paint event
void paintEvent(QPaintEvent *);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
//The common use of QPainter is inside a widget's paint event
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
//画笔
QPen pen(QColor(255, 0, 0));
pen.setWidth(3);
pen.setStyle(Qt::DashDotLine);
painter.setPen(pen);
painter.drawLine(QPoint(0, 0), QPoint(100, 100));//线
painter.drawEllipse(QPoint(100, 100), 20, 20);//圆
painter.drawEllipse(QPoint(100, 100), 50, 80);//椭圆
painter.drawRect(100, 100, 30, 30);//矩形
painter.drawRect(100, 100, 30, 80);
painter.drawText(100, 100, "I love you, Rick!");
//画刷
QBrush brush(Qt::green, Qt::Dense3Pattern);
painter.setBrush(brush);
painter.drawRect(200, 200, 50, 80);
//QConicalGradient与QBrush结合使用,以指定锥形渐变画笔。
QConicalGradient conicalGradient(QPointF(200, 100), 0);
conicalGradient.setColorAt(0.2, Qt::cyan);
conicalGradient.setColorAt(0.4, Qt::black);
conicalGradient.setColorAt(0.7, Qt::red);
conicalGradient.setColorAt(1, Qt::yellow);
painter.setBrush(conicalGradient);
painter.drawEllipse(QPointF(200, 100), 50, 50);
}
抗锯齿与坐标系变换
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
/*
//1.Antialliasing, translate
painter.setPen(QPen(Qt::red, 15));
painter.drawEllipse(QPoint(200, 150), 100, 100);
painter.setRenderHints(QPainter::Antialiasing);//抗锯齿
painter.translate(200, 0);//图形平移变换
painter.drawEllipse(QPoint(200, 150), 100, 100);
*/
//2.rotate旋转
/*
painter.setPen(QPen(Qt::red, 10));
painter.drawLine(QPoint(10, 10), QPoint(100, 100));
painter.save();
painter.translate(200, 0);
painter.rotate(90);
painter.setPen(QPen(Qt::blue, 10));
painter.drawLine(QPoint(10, 10), QPoint(100, 100));
painter.restore();
*/
//3.scale缩放
/*
painter.setPen(QPen(Qt::red));
painter.setBrush(Qt::yellow);
painter.drawRect(50, 50, 50, 50);
painter.save();
painter.scale(0.5, 0.5);
painter.setBrush(Qt::green);
painter.drawRect(50, 50, 50, 50);
painter.restore();
*/
//4.shear
painter.setPen(QPen(Qt::blue));
painter.setBrush(Qt::yellow);
painter.drawRect(50, 50, 50, 50);
painter.save();
painter.shear(0.5, 0.5);
painter.setBrush(Qt::gray);
painter.drawRect(50, 50, 50, 50);
painter.restore();
}
void QPainter::setRenderHint(QPainter:RenderHint hint,bool on=true)
如果on为true,则在画家上设置给定的渲染提示;否则清除渲染提示。
void QPainter::translate(const QPointF&offset)
按给定的偏移量转换坐标系;即,将给定的偏移量加到点上。
void QPainter::translate(const QPoint&offset)
这是一个重载函数。按给定的偏移量转换坐标系。
void QPainter::translate(qreal dx,qreal dy)
这是一个重载函数。将坐标系转换为向量(dx,dy)。
void QPainter::save()
保存当前画家状态(将状态推送到堆栈上)。save()后面必须跟有相应的restore();end()函数解除堆栈的绑定。
void QPainter::restore()
恢复当前画家状态(从堆栈中弹出已保存的状态)。
void QPainter::rotate(qreal angle)
顺时针旋转坐标系。给定的角度参数以度为单位。
void QPainter::scale(qreal sx,qreal sy)
按(sx,sy)缩放坐标系。
void QPainter::shear(qreal sh,qreal sv)
通过(sh,sv)剪切坐标系。
绘制字体与路径
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QTimer>
#include <QPainterPath>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
//QFont font("华文琥珀", 20, QFont::Bold, true);
QFont font("宋体", 30, QFont::Bold, true);
font.setUnderline(true);
painter.setFont(font);
painter.setPen(Qt::blue);
painter.drawText(50, 50, "I love you Rick!");
//QPainter painter(this);
QPainterPath path;
path.moveTo(50, 250);
path.lineTo(50,200);
path.lineTo(100, 100);
path.addEllipse(QPoint(100, 100), 30, 30);
painter.setPen(Qt::red);
painter.drawPath(path);
path.translate(200, 0);
painter.setPen(Qt::blue);
painter.drawPath(path);
}
void QPainterPath::moveTo(const QPointF &point)
将当前点移动到给定点,隐式地开始一个子路径并关闭上一个子路径。
void QPainterPath::lineTo(const QPointF&endPoint)
添加一条从当前位置到给定端点的直线。绘制线条后,当前位置将更新为线条的终点。
绘制曲线
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
resize(1600, 900);
setStyleSheet("background-color: balck");
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPen pen;
pen.setColor(Qt::green);
painter.setPen(pen);
painter.drawArc(25, 25, 1550, 1550, 0 * 16, 180 * 16);
painter.drawArc(180, 180, 1240, 1240, 0 * 16, 180 * 16);
painter.drawArc(335, 335, 930, 930, 0 * 16, 180 * 16);
painter.drawArc(490, 490, 620, 620, 0 * 16, 180 * 16);
painter.drawArc(645, 645, 310, 310, 0 * 16, 180 * 16);
}
void QPainter::drawArc(const QRectF &rectangle,int startAngle,int spanAngle)
绘制由给定矩形、startAngle和spanAngles定义的弧。 起始角度和跨度角度必须以1/16度为单位指定,即一个完整的圆等于5760(16*360)。角度的正值表示逆时针方向,负值表示顺时针方向。零度在3点钟位置。
void QPainter::drawArc(int x,int y,int width,int height,int startAngle,int spanAngle)
绘制由从(x,y)开始的矩形定义的弧,具有指定的宽度和高度,以及给定的startAngle和spanAngle。
手动调用绘图事件处理函数(实现秒针)
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QTimer>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
angle = 0;
QTimer *timer = new QTimer(this);
timer->start(1000);
connect(timer, &QTimer::timeout, [&](){update();});
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *)
{
angle += 6;
if(angle == 360)
angle = 0;
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(width()/2, height()/2);
painter.drawEllipse(QPoint(0, 0), 120, 120);
painter.rotate(angle);
painter.drawLine(QPoint(0, 0), QPoint(100, 0));
}
屏幕录制 2024-07-25 222715
QPaintDevice
QPaintDevice的绘图功能目前由QWidget、QImage、QPixmap、QGLPixelBuffer、QPicture和QPrinter子类实现。
Qt提供了四个类来处理图像数据:QImage、QPixmap、QBitmap和QPicture。QImage针对I/O、直接像素访问和操作进行了设计和优化,而QPixmap则针对在屏幕上显示图像进行了设计与优化。QBitmap只是一个继承QPixmap的便利类,确保深度为1。如果QPixmap对象确实是位图,则isQBitmap()函数返回true,否则返回false。最后,QPicture类是一个记录和重放QPainter命令的绘图设备。
-
QPixmap:
-
用于表示一个像素图,尽管
QPixmap
的接口是平台无关的,但其底层实现可能会依赖于特定的平台特性。例如,不同操作系统上的图像处理库可能不同,Qt 会根据运行的平台使用相应的库。 -
支持图像的简单操作,如缩放和旋转。
-
通常用于在窗口小部件上显示图像。
-
只能在主线程中使用。
-
-
QPicture:
-
包含一系列图形项,如线条、形状和文本。
-
可以把这些项绘制到任何
QPainter
设备上。 -
适合用于存储和重放图形操作,例如,当需要将相同的图形绘制到不同的窗口或打印机时。
-
存储形式是二进制形式。
-
-
QImage:
-
表示一个用于高级图像处理的像素图。
-
支持多种图像格式和深度(1、4、8、12、15、16、24、30、32位)。
-
提供了广泛的像素级操作功能,如像素读写、图像转换等。
-
适合用于图像的生成、编辑和复杂变换,多用于图片的传输。
-
-
QBitmap:
-
是
QPixmap
的子类,表示一个单色或多色的位图。 -
主要用于创建蒙版和掩码,用于图像的透明处理。
-
通常与
QPixmap
一起使用,来定义图像的透明部分。
-
这些类在Qt中的使用场景和特点如下:
-
当需要在窗口部件上显示图像时,使用
QPixmap
。 -
当需要记录和重放一系列图形操作时,使用
QPicture
。 -
当需要进行高级图像处理,如像素级操作时,使用
QImage
。 -
当需要创建图像的透明效果或掩码时,使用
QBitmap
。
在实际应用中,这些类通常与QPainter
一起使用,QPainter
是一个绘画类,提供了一系列绘制图形项的方法。例如,在QWidget
的paintEvent
函数中,使用QPainter
来绘制图像、文本、线条等。
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
/* QPixmap
QPixmap pix(400, 300);
pix.fill(Qt::white);
QPainter painter(&pix);
painter.setPen(Qt::red);
painter.drawEllipse(QPoint(100, 100), 50 ,50);
pix.save("D://mypix.jpg");
*/
//QImage
QImage img(400, 300, QImage::Format_RGB32);
img.fill(Qt::white);
QPainter painter(&img);
painter.setPen(Qt::red);
painter.drawEllipse(QPoint(100, 100), 50 ,50);
img.save("E://myImage.jpg");
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QImage img;
img.load(":/Image/Image/optimus prime.jpeg");
for(int i = 50; i < 100; i++)
{
for(int j = 50; j < 100; j++)
{
QRgb rgb = qRgb(255, 0, 0);
img.setPixel(i, j, rgb);
}
}
painter.drawImage(0, 0, img);
}
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QPicture>
#include <QBitmap>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
/*
//QPicture 可以理解为是一个绘图的容器,里面保存有绘图的纪录和重绘制的指令
//存储的形式是二进制形式,也就是说我们无法双击打开picture文件
QPicture pic;
//QPainter painter(&pic);
QPainter painter;
painter.begin(&pic);
painter.setPen(Qt::red);
painter.drawEllipse(QPoint(100, 100), 50, 50);
painter.end();
pic.save("E://abc.xyz");
*/
QBitmap bm(400, 300);
QPainter painter(&bm);
painter.setPen(Qt::red);
painter.drawEllipse(QPoint(100, 100), 50, 50);
bm.save("E://bm.jpg");
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *)
{
/*
QPainter painter(this);
QPicture pic;
pic.load("E://abc.xyz");
painter.drawPicture(0, 0, pic);
*/
QPainter painter(this);
QBitmap bm;
bm.load("E://optimus prime.jpeg");
painter.drawPixmap(0, 0, bm);
}
QPainter
和 QPainterDevice
区别
QPainter
与QPaintDevice
和QPaintEngine
类一起构成了Qt绘画系统的基础。QPainter
是用于执行绘图操作的类。QPaintDevice
表示可以使用QPainter
进行绘图的设备。QPaintEngine
提供了画家在不同类型的设备上绘制的界面。如果画家处于活动状态,则device()
返回画家正在其上绘制的绘制设备,paintEngine()
返回画家当前正在其上操作的绘制引擎。
QPainter
QPainter
是一个绘图类,它提供了一个抽象的接口,用于在各种设备上绘制图形和文本。它是一个高级的绘图对象,可以与多种设备上下文一起使用,比如 QWidget
、QImage
、QPrinter
等。
QPainterDevice
QPainterDevice
是一个抽象基类,定义了与绘图设备相关的接口。它定义了所有绘图设备必须实现的方法和属性,比如:
-
像素尺寸:
width()
和height()
方法返回设备的像素尺寸。 -
分辨率:
logicalDpiX()
和logicalDpiY()
方法返回设备的逻辑分辨率。 -
颜色深度:
colorCount()
方法返回设备支持的颜色数量。 -
绘图设备类型:
paintDevice()
方法返回设备类型。
区别
-
功能定位:
QPainter
是一个绘图工具,提供了绘制操作的方法;而QPainterDevice
是一个设备接口,定义了绘图设备的基本属性和功能。 -
使用方式:
QPainter
通常与具体的绘图设备(如QWidget
或QImage
)一起使用,而QPainterDevice
是这些设备的抽象表示。 -
抽象层次:
QPainter
抽象了绘图操作,使得开发者不需要关心具体的设备类型;QPainterDevice
则抽象了设备的基本属性和功能。
示例
// 使用QPainter绘制到QWidget
QWidget widget;
QPainter painter(&widget);
painter.drawLine(10, 10, 100, 100);
// 使用QPainter绘制到QImage
QImage image(100, 100, QImage::Format_RGB32);
QPainter painter2(&image);
painter2.drawLine(10, 10, 90, 90);
// 获取QPainterDevice的属性
QPainterDevice *device = painter.device();
int width = device->width();
int height = device->height();
通过这种方式,QPainter
和 QPainterDevice
共同构成了 Qt 框架中强大的绘图系统。