Qt:玩转QPainter序列四

前言

接着干源码

正文

先看源码,然后我们逐条分析

QPainter 是一个强大的绘图类,用于在 QWidgetQImageQPixmap 等设备上进行绘图操作。下面我会详细解释你提到的各个函数和属性,并通过示例展示它们的用法。

1. font()setFont()

  • const QFont &font() const;
    返回当前使用的字体,第一个const不允许别人修改它,第二个const表示它不修改别人。
  • void setFont(const QFont &f);
    设置绘图使用的字体。
    看到这里我们简单看下QFont构造函数。

    QFont 类用于描述字体的属性,如字体家族、字号、字重、斜体等。第一个是默认构造就不说了。
1.1 QFont(const QString &family, int pointSize = -1, int weight = -1, bool italic = false);
  • 构造函数

    使用指定的字体家族、字号、字重和斜体属性创建一个 QFont 对象。

    参数:

    • family: 字符串类型,指定字体的家族名称,如 "Arial""Times New Roman" 等。
    • pointSize: 整数类型,指定字体的点大小。如果设置为 -1,则使用系统默认大小。
    • weight: 整数类型,指定字体的字重,范围为 099,也可以使用预定义的值如 QFont::NormalQFont::Bold。如果设置为 -1,则使用默认字重。
    • italic: 布尔类型,指定字体是否为斜体。默认为 false(非斜体)。
    cpp 复制代码
    QFont customFont("Arial", 12, QFont::Bold, true);
1.2 QFont(const QFont &font, QPaintDevice *pd); (仅在 Qt 5.x 版本可用)
  • 拷贝构造函数

    在指定的 QPaintDevice 上创建一个与现有 QFont 对象相同的字体。

    参数:

    • font: QFont 类型,作为模板的现有字体对象。
    • pd: 指向 QPaintDevice 的指针,指定要应用字体的设备。QPaintDevice 是一个抽象基类,QWidgetQPixmap 等都继承自它。
    cpp 复制代码
    QPaintDevice *device = ...;  // 假设这是一个有效的 QPaintDevice 指针
    QFont font("Arial", 12);
    QFont newFont(font, device);
1.3 QFont(const QFont &font, const QPaintDevice *pd);
  • 拷贝构造函数 (Qt 6.0及以上版本)

    在指定的 QPaintDevice 上创建一个与现有 QFont 对象相同的字体。

    参数:

    • font: QFont 类型,作为模板的现有字体对象。
    • pd: 指向 QPaintDevice 的常量指针,指定要应用字体的设备。

    这个构造函数与之前的版本类似,只是 pd 参数变为常量指针,以适应 Qt 6.0 及以上版本的接口变化。

1.4 QFont(const QFont &font);

  • 拷贝构造函数

    使用现有的 QFont 对象创建一个新的 QFont 对象。

    参数:

    • font: QFont 类型,作为模板的现有字体对象。
    cpp 复制代码
    QFont originalFont("Arial", 12);
    QFont copiedFont(originalFont);
示例:

2. fontMetrics()fontInfo()

  • QFontMetrics fontMetrics() const;
    返回当前字体的 QFontMetrics 对象,用于获取字体的度量信息(如文本的宽度和高度)。多用于处理文本布局。这种对象多半不能直接转换成字符串,需要借助该对象来访问该对对象的属性
  • QFontInfo fontInfo() const;
    返回当前字体的 QFontInfo 对象,用于获取字体的详细信息。这种对象多半不能直接转换成字符串,需要借助该对象来访问该对对象的属性
示例:
cpp 复制代码
QPainter painter(this);
QFont font("Arial", 16);
painter.setFont(font);
QFontMetrics metrics = painter.fontMetrics();
int textWidth = metrics.horizontalAdvance("Hello, QPainter!");
painter.drawText(50, 50, "Hello, QPainter!");

3. setPen()pen()

  • void setPen(const QColor &color);
    使用指定的颜色设置画笔。
  • void setPen(const QPen &pen);
    使用指定的 QPen 对象设置画笔。
  • void setPen(Qt::PenStyle style);
    设置画笔的样式。
  • const QPen &pen() const;
    返回当前的画笔。
    简单看一下QPen这个类

    QPen 类在 Qt 中用于定义如何绘制线条和边框,包括颜色、宽度、样式等属性。
QPen 构造函数详解
  1. QPen()

    • 解释 : 默认构造函数,创建一个默认的 QPen 对象,通常为黑色、实线、宽度为 1 像素。
  2. QPen(Qt::PenStyle)

    • 解释 : 这个构造函数允许通过指定线条样式来创建 QPen 对象,例如 Qt::SolidLineQt::DashLine 等。
    • 参数 :
      • Qt::PenStyle: 线条的样式,例如实线、虚线等。
  3. QPen(const QColor &color)

    • 解释 : 使用指定颜色创建 QPen 对象,其他属性使用默认值。
    • 参数 :
      • const QColor &color: 线条的颜色。
  4. QPen(const QBrush &brush, qreal width, Qt::PenStyle s = Qt::SolidLine, Qt::PenCapStyle c = Qt::SquareCap, Qt::PenJoinStyle j = Qt::BevelJoin)

    • 解释 : 这个构造函数允许指定更详细的线条属性,如使用 QBrush 设置的笔刷、线条宽度、样式、端点样式和连接样式。这个最常用,但是要注意这里的QBrush并不是填充图形样式而是改变外部线条的样式。
    • 参数 :
      • const QBrush &brush: 用于绘制线条的笔刷。
      • qreal width: 线条的宽度。
      • Qt::PenStyle s: 线条样式,默认为实线。
      • Qt::PenCapStyle c: 线条端点的样式,如方形端点、圆形端点等。
      • Qt::PenJoinStyle j: 线条连接处的样式,如斜角连接、圆角连接等。
  5. QPen(const QPen &pen) noexcept

    • 解释 : 拷贝构造函数,用于创建一个新的 QPen 对象,该对象是另一个 QPen 对象的副本。
    • 参数 :
      • const QPen &pen: 用于复制的 QPen 对象。
  6. QPen &operator=(const QPen &pen) noexcept

    • 解释 : 拷贝赋值运算符,用于将一个 QPen 对象的值赋给另一个 QPen 对象。
    • 参数 :
      • const QPen &pen: 被赋值的 QPen 对象。
  7. QPen(QPen &&other) noexcept

    • 解释 : 移动构造函数,用于高效地转移 QPen 对象的资源。通过这个构造函数,可以避免不必要的内存复制。
    • 参数 :
      • QPen &&other: 被移动的 QPen 对象。
  8. QPen &operator=(QPen &&other) noexcept

    • 解释 : 移动赋值运算符,将另一个 QPen 对象的资源转移给当前对象。
    • 参数 :
      • QPen &&other: 被移动的 QPen 对象。
noexcept 的作用

noexcept 是 C++11 引入的一个关键字,用于指明函数在执行过程中不会抛出异常。如果一个函数声明为 noexcept,编译器可以对该函数进行优化,因为它知道调用该函数不会触发异常机制。

示例一:
cpp 复制代码
void PlayQPainter::initcboPenStyle()
{
    //为画笔样式添加条目
    ui->cboPenStyle->addItem("Solid",static_cast<int>(Qt::SolidLine));
    ui->cboPenStyle->addItem("Dash",static_cast<int>(Qt::DashLine));
    ui->cboPenStyle->addItem("Dot",static_cast<int>(Qt::DotLine));
    ui->cboPenStyle->addItem("Dash Dot",static_cast<int>(Qt::DashDotLine));
    ui->cboPenStyle->addItem("Dash Dot Dot",static_cast<int>(Qt::DashDotDotLine));
    ui->cboPenStyle->addItem("None",static_cast<int>(Qt::NoPen));

    //连接信号与槽
    connect(ui->cboPenStyle,QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](){
        int index = ui->cboPenStyle->currentIndex();
        Qt::PenStyle style = (Qt::PenStyle)ui->cboPenStyle->itemData(index).toInt();
        ui->paintArea->setPenStyle(style);
    });
}


void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);
    QPainter painter(this);

    QPen pen;
    pen.setWidth(20);
    pen.setColor(Qt::green);
    pen.setStyle(m_penStyle);
    painter.setPen(pen);
    painter.drawRect(50,50,300,300);

}
示例二:
cpp 复制代码
void PlayQPainter::initcboLineBrush()
{
    //添加所有的Qt::BrushStyle
    ui->cboLineBrush->addItem("NoBrush",static_cast<int>(Qt::NoBrush));
    ui->cboLineBrush->addItem("Solid",static_cast<int>(Qt::SolidPattern));
    ui->cboLineBrush->addItem("Dense1",static_cast<int>(Qt::Dense1Pattern));
    ui->cboLineBrush->addItem("Dense2",static_cast<int>(Qt::Dense2Pattern));
    ui->cboLineBrush->addItem("Dense3",static_cast<int>(Qt::Dense3Pattern));
    ui->cboLineBrush->addItem("Dense4",static_cast<int>(Qt::Dense4Pattern));
    ui->cboLineBrush->addItem("Dense5",static_cast<int>(Qt::Dense5Pattern));
    ui->cboLineBrush->addItem("Dense6",static_cast<int>(Qt::Dense6Pattern));
    ui->cboLineBrush->addItem("Dense7",static_cast<int>(Qt::Dense7Pattern));
    ui->cboLineBrush->addItem("Horizontal",static_cast<int>(Qt::HorPattern));
    ui->cboLineBrush->addItem("Vertical",static_cast<int>(Qt::VerPattern));
    ui->cboLineBrush->addItem("Cross",static_cast<int>(Qt::CrossPattern));
    ui->cboLineBrush->addItem("Backward Diagonal",static_cast<int>(Qt::BDiagPattern));
    ui->cboLineBrush->addItem("Forward Diagonal",static_cast<int>(Qt::FDiagPattern));
    ui->cboLineBrush->addItem("Diagonal Cross",static_cast<int>(Qt::DiagCrossPattern));
    ui->cboLineBrush->addItem("Linear Gradient",static_cast<int>(Qt::LinearGradientPattern));
    ui->cboLineBrush->addItem("Radial Gradient",static_cast<int>(Qt::RadialGradientPattern));
    ui->cboLineBrush->addItem("Conical Gradient",static_cast<int>(Qt::ConicalGradientPattern));
    ui->cboLineBrush->addItem("Texture",static_cast<int>(Qt::TexturePattern));

    //连接信号与槽
    connect(ui->cboLineBrush,QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](){
        int index = ui->cboLineBrush->currentIndex();
        Qt::BrushStyle style = (Qt::BrushStyle)ui->cboLineBrush->itemData(index).toInt();
        ui->paintArea->setLineBrush(style);
    });
}


void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);
    QPainter painter(this);

    QBrush brush(Qt::green, m_lineBrushStyle);
    painter.setPen(QPen(brush,40));
    painter.drawRect(100,100,200,200);

}


4. setBrush()brush()

  • void setBrush(const QBrush &brush);
    使用指定的 QBrush 对象设置画刷。
  • void setBrush(Qt::BrushStyle style);
    设置画刷的样式。
  • const QBrush &brush() const;
    返回当前的画刷。

简单看一下QBrush

QBrush 是 Qt 中用于描述填充模式的类,可以填充颜色、渐变、图案或纹理。

4.1 QBrush 的构造函数

QBrush 提供了多种构造函数,用于初始化不同类型的画刷:

  • QBrush()

    • 功能:默认构造函数,创建一个未初始化的画刷,通常情况下表示没有填充。

    • 示例

      cpp 复制代码
      QBrush brush;
  • QBrush(Qt::BrushStyle style)

    • 功能:使用指定的画刷样式(如纯色、斜线、点状填充等)构造一个画刷。默认颜色为黑色。

    • 参数

      • styleQt::BrushStyle 枚举类型,表示画刷的样式。
    • 示例

      cpp 复制代码
      QBrush brush(Qt::DiagCrossPattern); // 斜十字图案
  • QBrush(const QColor &color, Qt::BrushStyle style = Qt::SolidPattern)

    • 功能:使用指定的颜色和画刷样式构造一个画刷。

    • 参数

      • colorQColor 对象,表示画刷的颜色。
      • styleQt::BrushStyle,指定画刷的样式,默认为 Qt::SolidPattern(实心填充)。
    • 示例

      cpp 复制代码
      QBrush brush(Qt::red, Qt::Dense5Pattern); // 红色和密集图案5
  • QBrush(const QPixmap &pixmap)

    • 功能 :使用指定的图像 (QPixmap) 构造一个画刷,用于图案填充。

    • 参数

      • pixmapQPixmap 对象,表示要用作填充图案的图像。
    • 示例

      cpp 复制代码
      QPixmap pixmap(":/images/pattern.png");
      QBrush brush(pixmap); // 使用图片作为填充图案
  • QBrush(const QGradient &gradient)

    • 功能 :使用指定的渐变 (QGradient) 构造一个画刷,用于渐变填充。

    • 参数

      • gradientQGradient 对象,表示渐变的定义。
    • 示例

      cpp 复制代码
      QLinearGradient gradient(0, 0, 100, 100);
      gradient.setColorAt(0, Qt::white);
      gradient.setColorAt(1, Qt::black);
      QBrush brush(gradient); // 使用渐变作为填充
示例:
cpp 复制代码
//添加到combox的代码和线条Brush(`QPen`的示例二)很像,这里就不添加了

void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);
    QPainter painter(this);

    QBrush brush(Qt::green,m_brushStyle);
    //渐变和纹理要单独处理
    if (m_brushStyle == Qt::LinearGradientPattern) {
        //线性渐变
        QLinearGradient linearGradient(0, 50, 100, 50);
        linearGradient.setColorAt(0.0, QColor("#ff9a9e"));
        linearGradient.setColorAt(0.5,QColor("#fd9a14"));
        linearGradient.setColorAt(1.0,QColor("#fad0c4"));
        painter.setBrush(linearGradient);
    } else if (m_brushStyle == Qt::RadialGradientPattern) {
        //Radial
        QRadialGradient radialGradient(50,50,50,70,70);
        radialGradient.setColorAt(0.0, QColor("#272727"));
        radialGradient.setColorAt(0.5,QColor("#fc9191"));
        radialGradient.setColorAt(1.0,QColor("#f9f9f9"));
        painter.setBrush(radialGradient);
    } else if (m_brushStyle == Qt::ConicalGradientPattern) {
        //Conical
        QConicalGradient conicalGradient(50,50,150);
        conicalGradient.setColorAt(0.0, QColor("#ff00cc"));
        conicalGradient.setColorAt(0.2,QColor("#ffcc00"));
        conicalGradient.setColorAt(0.5,QColor("#00ffcc"));
        conicalGradient.setColorAt(1.0,QColor("#ff0066"));
        painter.setBrush(conicalGradient);
    } else if (m_brushStyle == Qt::TexturePattern) {
        // 纹理/材质
        painter.setBrush(QBrush(QPixmap("D:/all_the_code/qt_code/ts/playQPainter/lyf.jpg")));
    } else {
        painter.setBrush(brush);
    }

    painter.drawRect(50,50,300,300);

}

渐变

纹理

5. setBackgroundMode()backgroundMode()(先已弃用)

  • void setBackgroundMode(Qt::BGMode mode);
    设置背景模式,Qt5.14.2目前只有这两种模式Qt::OpaqueMode(不透明模式) 和 Qt::TransparentMode(透明模式)。
  • Qt::BGMode backgroundMode() const;
    返回当前的背景模式。
    setBackgroundMode(Qt::TransparentMode)setBackgroundMode(Qt::OpaqueMode) 是 Qt 3.x 时代的方法,用于设置窗口小部件的背景模式。它们之间的区别主要在于控件的背景如何与父控件或其他背景内容进行叠加或覆盖。
5.1 Qt::TransparentMode
  • 透明模式 :当控件的背景模式设置为 Qt::TransparentMode 时,控件不会主动绘制其背景。这意味着控件的背景将变得透明,显示出其父控件的背景或底层的内容。
  • 效果:这种模式通常用于需要控件叠加显示的情况,例如在一个复杂的用户界面中,多个控件可能需要重叠显示。
5.2 Qt 4.x 及以后的版本

需要注意的是,从 Qt 4.x 开始,setBackgroundMode 方法已被弃用(既然已经弃用就不说了),Qt 使用了更灵活的机制来管理控件背景,例如 QPalette 和属性系统(如 Qt::WA_OpaquePaintEventQt::WA_TranslucentBackground)。这些新的机制提供了更多的控制和更高的绘制性能。

6. QPoint brushOrigin() const;void setBrushOrigin(int x, int y);void setBrushOrigin(const QPoint &);void setBrushOrigin(const QPointF &);

6.1QPoint brushOrigin() const;
  • 功能:返回当前画刷的原点位置。画刷原点用于控制画刷的起始位置,当填充图案时,这个原点决定了图案的对齐方式。
  • 返回值 :一个 QPoint 对象,表示当前画刷的原点位置。
6.2 void setBrushOrigin(int x, int y);
  • 功能:设置画刷的原点位置,使用整数坐标 (x, y) 来指定新的原点位置。
  • 参数
    • x:新的原点的 x 坐标。
    • y:新的原点的 y 坐标。
6.3 void setBrushOrigin(const QPoint &);
  • 功能 :设置画刷的原点位置,使用一个 QPoint 对象来指定新的原点位置。
  • 参数
    • QPoint &:表示新的原点位置的 QPoint 对象。
6.4 void setBrushOrigin(const QPointF &);
  • 功能 :设置画刷的原点位置,使用一个 QPointF 对象(即浮点数坐标)来指定新的原点位置。
  • 参数
    • QPointF &:表示新的原点位置的 QPointF 对象。

7. void setBackground(const QBrush &bg);const QBrush &background() const;

  • void setBackground(const QBrush &bg);

  • 功能:设置当前绘制环境的背景画刷。这个背景画刷通常在透明模式下使用,用于在绘制透明内容时填充背景。

  • 参数

    • QBrush &bg:用于绘制背景的 QBrush 对象。
  • const QBrush &background() const;

  • 功能:返回当前设置的背景画刷。

  • 返回值 :一个常量引用,指向当前使用的背景 QBrush 对象。

8. setOpacity()opacity()

  • qreal opacity() const;
    返回当前的透明度值。
  • void setOpacity(qreal opacity);
    设置透明度,取值范围为 01。这个我们上节说过,这里也就不过多赘述了。
示例:
cpp 复制代码
QPainter painter(this);
painter.setOpacity(0.5);
painter.drawEllipse(50, 50, 100, 100);

9. 裁剪家族

这篇写的太多了,裁剪家族留到下篇博客去写。

10. save()restore()

  • void save();
    保存当前的绘图状态(如笔、画刷、变换等)。
  • void restore();
    恢复到上次 save() 时保存的状态。
示例:
cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);
    QPainter painter(this);

    QBrush brush(Qt::green,m_brushStyle);
    painter.setPen(QPen(Qt::red));
    painter.setBrush(brush);
    painter.save();
    painter.drawRect(50,50,300,300);
    QPen pen;
    pen.setColor(Qt::green);
    pen.setWidth(10);
    pen.setStyle(Qt::DashDotDotLine);
    painter.setPen(pen);
    painter.drawRect(150,150,100,100);
    //恢复之后
    painter.restore();
    painter.drawRect(250,250,50,50);


}
相关推荐
Ajiang28247353042 小时前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
幽兰的天空2 小时前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
Theodore_10225 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
----云烟----7 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024067 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic7 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it7 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康7 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神8 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
宅小海8 小时前
scala String
大数据·开发语言·scala