前言
最近想潜心研究一下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_NAMESPACEQT_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来加载