前言
接着干源码
正文
先看源码,然后我们逐条分析
QPainter
是一个强大的绘图类,用于在 QWidget
、QImage
、QPixmap
等设备上进行绘图操作。下面我会详细解释你提到的各个函数和属性,并通过示例展示它们的用法。
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
: 整数类型,指定字体的字重,范围为0
到99
,也可以使用预定义的值如QFont::Normal
、QFont::Bold
。如果设置为-1
,则使用默认字重。italic
: 布尔类型,指定字体是否为斜体。默认为false
(非斜体)。
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
是一个抽象基类,QWidget
、QPixmap
等都继承自它。
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
类型,作为模板的现有字体对象。
QFont originalFont("Arial", 12); QFont copiedFont(originalFont);
示例:
2. fontMetrics()
和 fontInfo()
QFontMetrics fontMetrics() const;
返回当前字体的QFontMetrics
对象,用于获取字体的度量信息(如文本的宽度和高度)。多用于处理文本布局。这种对象多半不能直接转换成字符串,需要借助该对象来访问该对对象的属性QFontInfo fontInfo() const;
返回当前字体的QFontInfo
对象,用于获取字体的详细信息。这种对象多半不能直接转换成字符串,需要借助该对象来访问该对对象的属性
示例:
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
构造函数详解
-
QPen()
- 解释: 默认构造函数,创建一个默认的
QPen
对象,通常为黑色、实线、宽度为 1 像素。
- 解释: 默认构造函数,创建一个默认的
-
QPen(Qt::PenStyle)
- 解释: 这个构造函数允许通过指定线条样式来创建
QPen
对象,例如Qt::SolidLine
、Qt::DashLine
等。 - 参数:
Qt::PenStyle
: 线条的样式,例如实线、虚线等。
- 解释: 这个构造函数允许通过指定线条样式来创建
-
QPen(const QColor &color)
- 解释: 使用指定颜色创建
QPen
对象,其他属性使用默认值。 - 参数:
const QColor &color
: 线条的颜色。
- 解释: 使用指定颜色创建
-
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
: 线条连接处的样式,如斜角连接、圆角连接等。
- 解释: 这个构造函数允许指定更详细的线条属性,如使用
-
QPen(const QPen &pen) noexcept
- 解释: 拷贝构造函数,用于创建一个新的
QPen
对象,该对象是另一个QPen
对象的副本。 - 参数:
const QPen &pen
: 用于复制的QPen
对象。
- 解释: 拷贝构造函数,用于创建一个新的
-
QPen &operator=(const QPen &pen) noexcept
- 解释: 拷贝赋值运算符,用于将一个
QPen
对象的值赋给另一个QPen
对象。 - 参数:
const QPen &pen
: 被赋值的QPen
对象。
- 解释: 拷贝赋值运算符,用于将一个
-
QPen(QPen &&other) noexcept
- 解释: 移动构造函数,用于高效地转移
QPen
对象的资源。通过这个构造函数,可以避免不必要的内存复制。 - 参数:
QPen &&other
: 被移动的QPen
对象。
- 解释: 移动构造函数,用于高效地转移
-
QPen &operator=(QPen &&other) noexcept
- 解释: 移动赋值运算符,将另一个
QPen
对象的资源转移给当前对象。 - 参数:
QPen &&other
: 被移动的QPen
对象。
- 解释: 移动赋值运算符,将另一个
noexcept
的作用
noexcept
是 C++11 引入的一个关键字,用于指明函数在执行过程中不会抛出异常。如果一个函数声明为 noexcept
,编译器可以对该函数进行优化,因为它知道调用该函数不会触发异常机制。
示例一:
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);
}
示例二:
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()
- 功能:默认构造函数,创建一个未初始化的画刷,通常情况下表示没有填充。
- 示例:
QBrush brush;
-
QBrush(Qt::BrushStyle style)
- 功能:使用指定的画刷样式(如纯色、斜线、点状填充等)构造一个画刷。默认颜色为黑色。
- 参数:
style
:Qt::BrushStyle
枚举类型,表示画刷的样式。
- 示例:
QBrush brush(Qt::DiagCrossPattern); // 斜十字图案
-
QBrush(const QColor &color, Qt::BrushStyle style = Qt::SolidPattern)
- 功能:使用指定的颜色和画刷样式构造一个画刷。
- 参数:
color
:QColor
对象,表示画刷的颜色。style
:Qt::BrushStyle
,指定画刷的样式,默认为Qt::SolidPattern
(实心填充)。
- 示例:
QBrush brush(Qt::red, Qt::Dense5Pattern); // 红色和密集图案5
-
QBrush(const QPixmap &pixmap)
- 功能:使用指定的图像 (
QPixmap
) 构造一个画刷,用于图案填充。 - 参数:
pixmap
:QPixmap
对象,表示要用作填充图案的图像。
- 示例:
QPixmap pixmap(":/images/pattern.png"); QBrush brush(pixmap); // 使用图片作为填充图案
- 功能:使用指定的图像 (
-
QBrush(const QGradient &gradient)
- 功能:使用指定的渐变 (
QGradient
) 构造一个画刷,用于渐变填充。 - 参数:
gradient
:QGradient
对象,表示渐变的定义。
- 示例:
QLinearGradient gradient(0, 0, 100, 100); gradient.setColorAt(0, Qt::white); gradient.setColorAt(1, Qt::black); QBrush brush(gradient); // 使用渐变作为填充
- 功能:使用指定的渐变 (
示例:
//添加到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_OpaquePaintEvent
、Qt::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);
设置透明度,取值范围为0
到1
。这个我们上节说过,这里也就不过多赘述了。
示例:
QPainter painter(this);
painter.setOpacity(0.5);
painter.drawEllipse(50, 50, 100, 100);
9. 裁剪家族
这篇写的太多了,裁剪家族留到下篇博客去写。
10. save()
和 restore()
void save();
保存当前的绘图状态(如笔、画刷、变换等)。void restore();
恢复到上次save()
时保存的状态。
示例:
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);
}