前言
最近想潜心研究一下QPainter这个类,最好把QPainter所有的函数都敲一遍,特地记录一下。
在说QPainter
之前我们需要了解两个非常重要的东西
第一个坐标系
我用两张图来表示
代码实操的结果
更加详细的坐标系内容请看我的另一篇博客
第二个是有关绘图的一些基本概念
QPainter
:Qt中的绘图类,用于在各种设备上进行绘图操作。
QPen
:用于定义线条的颜色、宽度和样式。
QBrush
:用于定义填充区域的颜色、渐变和图案。
QPixmap
:用于表示位图图像。
QImage
:用于表示图像,支持像素级别的操作。
正文
下面是QPainter的类定义开头一部分,我们逐行开始分析
1. 头文件保护符:
cpp
#ifndef QPAINTER_H
#define QPAINTER_H
这段代码用于防止头文件的重复包含。
#ifndef QPAINTER_H
是在检查 QPAINTER_H
是否未定义。
如果未定义,则使用 #define QPAINTER_H
来定义它。
这样当此文件被多次包含时,后续的包含将不会重复定义 QPAINTER_H
,从而避免编译错误。
2. 头文件的包含:
cpp
#include <QtGui/qtguiglobal.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qrect.h>
#include <QtCore/qpoint.h>
#include <QtCore/qscopedpointer.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qimage.h>
#include <QtGui/qtextoption.h>
这些 #include
指令用于将其他必要的头文件包含到当前文件中。
QtGui/qtguiglobal.h
包含与Qt GUI模块相关的全局定义。QtCore/qnamespace.h
包含命名空间相关的定义。qrect.h
和qpoint.h
是与几何对象相关的头文件,定义了矩形和点的类。qscopedpointer.h
提供了智能指针的功能,用于内存管理。qpixmap.h
和qimage.h
是处理图像和位图的类的头文件。qtextoption.h
包含与文本显示选项相关的定义。
3. 条件性包含:
cpp
#ifndef QT_INCLUDE_COMPAT
#include <QtGui/qpolygon.h>
#include <QtGui/qpen.h>
#include <QtGui/qbrush.h>
#include <QtGui/qmatrix.h>
#include <QtGui/qtransform.h>
#include <QtGui/qfontinfo.h>
#include <QtGui/qfontmetrics.h>
#endif
这部分代码表示,当 QT_INCLUDE_COMPAT
未定义时,才会包含这些头文件。
这些文件中包含了与多边形、画笔、刷子、矩阵变换、字体信息、字体度量等相关的类。
4. 命名空间开始:
cpp
QT_BEGIN_NAMESPACE
QT_BEGIN_NAMESPACE
是一个宏,用于标记Qt库的命名空间的开始。
它通常与 QT_END_NAMESPACE
搭配使用,用于确保在不同的编译环境中命名空间的正确使用。
这是下面一部分的定义,继续看
1. 前置声明(Forward Declarations):
cpp
class QBrush;
class QFontInfo;
class QFontMetrics;
class QPaintDevice;
class QPainterPath;
class QPainterPrivate;
class QPen;
class QPolygon;
class QTextItem;
class QTextEngine;
class QMatrix;
class QTransform;
class QStaticText;
class QGlyphRun;
class QPainterPrivateDeleter;
这些是类的前置声明。前置声明是告诉编译器这些类的名称和它们是类类型,而不提供它们的完整定义。
这样做的目的是提高编译效率,避免包含不必要的头文件。
在需要使用这些类的指针或引用时,可以仅使用前置声明,而不需要完整的类定义。
2. 类的声明:
cpp
class Q_GUI_EXPORT QPainter{}
QPainter
是一个用来执行绘图操作的类。在Qt中,QPainter
类提供了绘制文本、图像、线条和其他图形元素的方法。
Q_GUI_EXPORT
是一个宏,用于导出这个类,使其在动态链接库(DLL)中可用。
3. 宏定义:
cpp
Q_DECLARE_PRIVATE(QPainter)
Q_GADGET
-
Q_DECLARE_PRIVATE(QPainter)
是一个宏,用于声明一个指向该类的私有数据指针d_ptr
。这是Qt中常用的一个设计模式,用来实现Pimpl(Pointer to Implementation)技术,分离接口和实现,增强封装性。 -
Q_GADGET
是一个用于声明轻量级的Qt对象的宏。虽然它不像QObject
那样支持信号和槽,但它可以使用元对象系统的其他功能,比如枚举的元信息。
4. 公共部分 (public
):
cpp
public:
enum RenderHint {
Antialiasing = 0x01,
TextAntialiasing = 0x02,
SmoothPixmapTransform = 0x04,
#if QT_DEPRECATED_SINCE(5, 14)
HighQualityAntialiasing Q_DECL_ENUMERATOR_DEPRECATED_X("Use Antialiasing instead") = 0x08,
NonCosmeticDefaultPen Q_DECL_ENUMERATOR_DEPRECATED_X("Default pen is non-cosmetic now") = 0x10,
#endif
Qt4CompatiblePainting = 0x20,
LosslessImageRendering = 0x40,
};
public
表示这一部分的成员可以被类的外部访问。
-
RenderHint
是QPainter
类中的一个枚举类型,用于指定绘图时的渲染提示。渲染提示是一些位掩码值,用于控制绘图的质量和性能。Antialiasing = 0x01
:启用抗锯齿,以获得平滑的图形边缘。TextAntialiasing = 0x02
:启用文本的抗锯齿处理。SmoothPixmapTransform = 0x04
:启用平滑的位图变换。
枚举中还包括一些已弃用的选项,用
QT_DEPRECATED_SINCE(5, 14)
来标记。HighQualityAntialiasing
:高质量抗锯齿处理,但已弃用,建议使用Antialiasing
代替。NonCosmeticDefaultPen
:默认笔非装饰性,但已弃用。
其他选项:
Qt4CompatiblePainting = 0x20
:启用与Qt 4兼容的绘图模式。LosslessImageRendering = 0x40
:启用无损图像渲染,确保图像质量。
OK现在我们写一个小例子来测试这些渲染
cpp
void PlayQPainter::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// 设置当前的渲染提示
//painter.setRenderHint(QPainter::Antialiasing,true);
// 绘制不同的图形以展示渲染效果
painter.drawEllipse(50, 50, 200, 200); // 画圆
painter.drawText(100, 300, "没有开始渲染时的效果!"); // 画文本
// 绘制图像(假设有一个图像)
painter.drawPixmap(50, 350, QPixmap("D:/all_the_code/qt_code/ts/playQPainter/lyf.jpg"));
// 测试其他几何图形
painter.drawRect(300, 50, 200, 200); // 画矩形
painter.drawLine(550, 50, 580, 580); // 画线条
}
没有开启渲染时可以看到线条有许多锯齿状
cpp
void PlayQPainter::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// 设置当前的渲染提示
painter.setRenderHint(QPainter::Antialiasing,true);
// 绘制不同的图形以展示渲染效果
painter.drawEllipse(50, 50, 200, 200); // 画圆
painter.drawText(100, 300, "开启平滑抗锯齿时的效果!"); // 画文本
// 绘制图像(假设有一个图像)
painter.drawPixmap(50, 350, QPixmap("D:/all_the_code/qt_code/ts/playQPainter/lyf.jpg"));
// 测试其他几何图形
painter.drawRect(300, 50, 200, 200); // 画矩形
painter.drawLine(550, 50, 580, 580); // 画线条
}
可以看到线条平滑了许多
cpp
void PlayQPainter::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QFont font;
font.setPointSize(20);
painter.setFont(font);
// 设置当前的渲染提示
painter.setRenderHint(QPainter::TextAntialiasing,true);
// 绘制不同的图形以展示渲染效果
painter.drawEllipse(50, 50, 200, 200); // 画圆
painter.drawText(100, 300, "开启文本抗锯齿时的效果!"); // 画文本
// 绘制图像(假设有一个图像)
painter.drawPixmap(50, 350, QPixmap("D:/all_the_code/qt_code/ts/playQPainter/lyf.jpg"));
// 测试其他几何图形
painter.drawRect(300, 50, 200, 200); // 画矩形
painter.drawLine(550, 50, 580, 580); // 画线条
}
使用文本抗锯齿对文本影响很小,至少在我这边运行时是这样。
平滑位图变换我就不测试了,它是要用QImage
来加载图片,而不是用QPainter
来加载