前言
本章源码主要就是各种函数画各种图形。
正文
1. drawRects
系列函数 绘制矩形
-
void drawRects(const QRectF *rects, int rectCount);
- 使用
QRectF
数组绘制rectCount
个矩形。
- 使用
-
inline void drawRects(const QVector<QRectF> &rectangles);
- 使用
QVector<QRectF>
对象绘制多个矩形。
- 使用
-
void drawRects(const QRect *rects, int rectCount);
- 使用
QRect
数组绘制rectCount
个矩形。
- 使用
-
inline void drawRects(const QVector<QRect> &rectangles);
- 使用
QVector<QRect>
对象绘制多个矩形。
- 使用
示例
void PaintWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置粗一点
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
QRect rects[] = {
//矩形左上角位于(0,0),宽30,高40
QRect(10,10,30,40),
QRect(50,10,30,40),
QRect(90,10,30,40)
};
int rectsCount = sizeof(rects) / sizeof(rects[0]);
painter.drawRects(rects,rectsCount);
QVector<QRect> vrects;
vrects<< QRect(10,60,30,40)
<< QRect(50,60,30,40)
<< QRect(90,60,30,40);
pen.setColor(Qt::green);
painter.setPen(pen);
painter.drawRects(vrects);
}
2. drawEllipse
系列函数 绘制椭圆
-
void drawEllipse(const QRectF &r);
- 在给定的
QRectF
边界内绘制椭圆。
- 在给定的
-
void drawEllipse(const QRect &r);
- 在给定的
QRect
边界内绘制椭圆。
- 在给定的
-
inline void drawEllipse(int x, int y, int w, int h);
- 在指定的
(x, y)
坐标和宽度、高度为w
和h
的矩形内绘制椭圆。
- 在指定的
-
inline void drawEllipse(const QPointF ¢er, qreal rx, qreal ry);
- 在指定的
QPointF
中心绘制半径为rx
和ry
的椭圆。
- 在指定的
-
inline void drawEllipse(const QPoint ¢er, int rx, int ry);
- 在指定的
QPoint
中心绘制半径为rx
和ry
的椭圆。
- 在指定的
示例
void PaintWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置粗一点
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
QRect rect(30,40,50,50),rect2(80,10,30,40);
//在rect内画一个椭圆,如rect为正方形,则画圆
painter.drawEllipse(rect);
painter.drawEllipse(rect2);
//若rx = ry则画圆,否则为椭圆
pen.setColor(Qt::gray);
painter.setPen(pen);
QPoint point(100,100);
painter.drawEllipse(point,30,30);
painter.drawEllipse(point,60,50);
}
3. drawPolyline
系列函数 绘制折线
使用绘制折线,系统不会将你首尾两个点相连,当然可以自己添加一个点使得首尾相连
-
void drawPolyline(const QPointF *points, int pointCount);
- 使用
QPointF
数组绘制pointCount
个点连接成的折线。
- 使用
-
inline void drawPolyline(const QPolygonF &polyline);
- 使用
QPolygonF
对象绘制折线。
- 使用
-
void drawPolyline(const QPoint *points, int pointCount);
- 使用
QPoint
数组绘制pointCount
个点连接成的折线。
- 使用
-
inline void drawPolyline(const QPolygon &polygon);
- 使用
QPolygon
对象绘制折线。
- 使用
示例
void PaintWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置粗一点
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
QPoint points[] = {
QPoint(10,10),
QPoint(35,80),
QPoint(65,24),
QPoint(10,10)
};
int pointsCount = sizeof(points) / sizeof(points[0]);
//使用首尾相同的点会形成闭合的图形
painter.drawPolyline(points,pointsCount);
QPolygon polygon;
polygon << QPoint(80,80)
<< QPoint(100,20)
<< QPoint(40,90);
pen.setColor(Qt::green);
painter.setPen(pen);
painter.drawPolyline(polygon);
}
4. drawPolygon
系列函数 绘制多边形
使用绘制多边形,系统会将你首尾两个点相连
-
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule = Qt::OddEvenFill);
- 使用
QPointF
数组绘制多边形。fillRule
参数决定填充规则(例如OddEvenFill
或WindingFill
)。
- 使用
-
inline void drawPolygon(const QPolygonF &polygon, Qt::FillRule fillRule = Qt::OddEvenFill);
- 使用
QPolygonF
对象绘制多边形,fillRule
指定填充规则。
- 使用
-
void drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule = Qt::OddEvenFill);
- 使用
QPoint
数组绘制多边形,fillRule
指定填充规则。
- 使用
-
inline void drawPolygon(const QPolygon &polygon, Qt::FillRule fillRule = Qt::OddEvenFill);
- 使用
QPolygon
对象绘制多边形,fillRule
指定填充规则。
- 使用
这里Qt::FillRule
只有两种规则OddEvenFill
与WindingFill
,OddEvenFill
是默认填充规则。它们的区别主要体现在如何确定一个点是否在多边形的内部。
1. OddEvenFill
填充规则
OddEvenFill 是一种简单的填充规则,通常用于确定一个点是否在多边形内部。判断方式如下:
- 规则:从要检测的点向任意方向绘制一条直线,统计这条直线与多边形边界的交点数。如果交点数为奇数,则认为该点在多边形内部;如果为偶数,则认为该点在多边形外部。
示例:
考虑一个八字形的多边形。如果一条直线穿过多边形的边界的次数是奇数,那么它内部的区域将会被填充。假设有两个重叠的区域,中间的重叠部分因为交点数为偶数,所以不会被填充。
2. WindingFill
填充规则
WindingFill 是另一种更复杂的填充规则,考虑了多边形边界的方向。判断方式如下:
- 规则:从要检测的点向任意方向绘制一条直线,计算直线与多边形边界交点的环绕数(即“绕数”)。当绕数为非零时,认为该点在多边形内部;为零时,该点在多边形外部。绕数通过多边形边界的方向(顺时针或逆时针)来计算。
计算绕数:
- 如果从点出发的直线与多边形的边从左向右相交,则绕数加1;
- 如果从右向左相交,则绕数减1;
- 经过所有交点之后,如果绕数不为0,则点在多边形内部。
示例:
如果同样是八字形的多边形,由于考虑了绕数,重叠区域内的所有点都将被填充,因为这些点的绕数非零。
- OddEvenFill:通过交点的奇偶性判断点是否在多边形内部,适合简单的形状。
- WindingFill:通过计算绕数判断点是否在多边形内部,适合复杂的、多环绕的形状。
示例
void PaintWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置粗一点
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
// 定义一个复杂的多边形形状
QPolygon polygon;
polygon << QPoint(50, 150) << QPoint(150, 50) << QPoint(250, 150)
<< QPoint(150, 250) << QPoint(100, 100) << QPoint(200, 100);
// 使用 Qt::OddEvenFill 填充规则绘制多边形
painter.setBrush(Qt::red);
painter.drawPolygon(polygon, Qt::OddEvenFill);
// 在另一个位置使用 Qt::WindingFill 填充规则绘制相同的多边形
painter.translate(300, 0);
painter.setBrush(Qt::blue);
painter.drawPolygon(polygon, Qt::WindingFill);
}
5. drawConvexPolygon
系列函数 绘制凸多边形
凸多边形(凸多边形的所有内部角小于 180°)。
-
void drawConvexPolygon(const QPointF *points, int pointCount);
- 使用
QPointF
数组绘制凸多边形。
- 使用
-
inline void drawConvexPolygon(const QPolygonF &polygon);
- 使用
QPolygonF
对象绘制凸多边形。
- 使用
-
void drawConvexPolygon(const QPoint *points, int pointCount);
- 使用
QPoint
数组绘制凸多边形。
- 使用
-
inline void drawConvexPolygon(const QPolygon &polygon);
- 使用
QPolygon
对象绘制凸多边形。
- 使用
示例
void PaintWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置粗一点
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
// 定义一个凸多边形形状,使用 QPoint 数组
QPoint points1[] = {
QPoint(50, 100),
QPoint(150, 50),
QPoint(250, 100),
QPoint(200, 200),
QPoint(100, 200)
};
int pointCount1 = sizeof(points1) / sizeof(points1[0]);
// 使用 QPoint 数组绘制凸多边形
painter.setBrush(Qt::green);
painter.drawConvexPolygon(points1, pointCount1);
// 定义一个凸多边形形状,使用 QPolygon 对象
QPolygon polygon;
polygon << QPoint(350, 100) << QPoint(450, 50) << QPoint(550, 100)
<< QPoint(500, 200) << QPoint(400, 200);
// 使用 QPolygon 对象绘制凸多边形
painter.setBrush(Qt::yellow);
painter.drawConvexPolygon(polygon);
}
6. drawArc
系列函数 绘制弧线。
-
void drawArc(const QRectF &rect, int a, int alen);
- 在指定的
QRectF
边界内绘制弧线,从角度a
开始,弧长为alen
。
- 在指定的
-
inline void drawArc(const QRect &, int a, int alen);
- 在指定的
QRect
边界内绘制弧线。
- 在指定的
-
inline void drawArc(int x, int y, int w, int h, int a, int alen);
- 在指定的矩形边界
(x, y, w, h)
内绘制弧线。
- 在指定的矩形边界
下面是一个使用 QPainter
的 drawArc
函数绘制弧线的示例,并讨论绘制弧线时的一些注意事项。
示例代码
#include <QApplication>
#include <QWidget>
#include <QPainter>
class ArcWidget : public QWidget
{
protected:
void paintEvent(QPaintEvent *event) override
{
QPainter painter(this);
// 设置画笔和画刷
QPen pen(Qt::blue, 2);
painter.setPen(pen);
// 定义矩形区域用于绘制弧线
QRect rect(50, 50, 200, 200);
// 设置弧线的起始角度和弧长(16分之一度)
int startAngle = 30 * 16; // 30度
int spanAngle = 120 * 16; // 120度
// 绘制弧线
painter.drawArc(rect, startAngle, spanAngle);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ArcWidget window;
window.resize(300, 300);
window.show();
return app.exec();
}
注意事项
-
角度表示方法:
- 在
drawArc
中,角度是以16分之一度为单位的。例如,30度对应的值为30 * 16
,完整的一圈(360度)对应的值为360 * 16 = 5760
。 - 起始角度
a
是相对于水平轴的角度,正值表示顺时针方向,负值表示逆时针方向。 起始角度可以任意选择,但常见的起点是0度(水平右侧)。
- 在
-
弧长选择:
alen
是弧的跨度,表示弧线从起始角度向顺时针方向的延展长度,也以16分之一度为单位。- 如果
alen
为正,弧线将顺时针绘制;如果为负,则逆时针绘制。 - 弧长通常取决于所需的弧的大小,例如
90 * 16
(90度)用于绘制1/4圆,180 * 16
(180度)用于绘制半圆。
示例
void PaintWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置粗一点
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
// 定义矩形区域用于绘制弧线
QRect rect(50, 50, 200, 200);
// 设置弧线的起始角度和弧长(16分之一度)
int startAngle = 30 * 16; // 30度
int spanAngle = 120 * 16; // 120度
// 绘制弧线
painter.drawArc(rect, startAngle, spanAngle);
}
7. drawPie
系列函数 绘制饼形
这些函数用于绘制饼形。
-
void drawPie(const QRectF &rect, int a, int alen);
- 在指定的
QRectF
边界内绘制饼形,从角度a
开始,饼形弧长为alen
。
- 在指定的
-
inline void drawPie(int x, int y, int w, int h, int a, int alen);
- 在指定的矩形边界
(x, y, w, h)
内绘制饼形。
- 在指定的矩形边界
-
inline void drawPie(const QRect &, int a, int alen);
- 在指定的
QRect
边界内绘制饼形。
- 在指定的
示例
void PaintWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置粗一点
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
// 定义矩形区域用于绘制弧线
QRect rect(50, 50, 200, 200);
// 设置弧线的起始角度和弧长(16分之一度)
int startAngle = 30 * 16; // 30度
int spanAngle = 120 * 16; // 120度
painter.setBrush(Qt::green);
// 绘制饼形
painter.drawPie(rect, startAngle, spanAngle);
}
8. drawChord
系列函数 绘制弦
弦(由弧线和直线连接的部分)。
-
void drawChord(const QRectF &rect, int a, int alen);
- 在指定的
QRectF
边界内绘制弦,从角度a
开始,弧长为alen
。
- 在指定的
-
inline void drawChord(int x, int y, int w, int h, int a, int alen);
- 在指定的矩形边界
(x, y, w, h)
内绘制弦。
- 在指定的矩形边界
-
inline void drawChord(const QRect &, int a, int alen);
- 在指定的
QRect
边界内绘制弦。
- 在指定的
示例
void PaintWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置粗一点
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
// 定义矩形区域用于绘制弧线
QRect rect(50, 50, 200, 200);
// 设置弧线的起始角度和弧长(16分之一度)
int startAngle = 30 * 16; // 30度
int spanAngle = 120 * 16; // 120度
painter.setBrush(Qt::green);
// 绘制弦
painter.drawChord(rect, startAngle, spanAngle);
}
9. drawRoundedRect
系列函数 绘制圆角矩形
-
void drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize);
- 在指定的
QRectF
边界内绘制圆角矩形,xRadius
和yRadius
分别是水平和垂直方向的圆角半径。
- 在指定的
-
inline void drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize);
- 在指定的矩形边界
(x, y, w, h)
内绘制圆角矩形。
- 在指定的矩形边界
-
inline void drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize);
- 在指定的
QRect
边界内绘制圆角矩形。
- 在指定的
下面是使用 QPainter
的 drawRoundedRect
函数绘制带圆角矩形的示例,并讨论一些注意事项。
示例代码
#include <QApplication>
#include <QWidget>
#include <QPainter>
class RoundedRectWidget : public QWidget
{
protected:
void paintEvent(QPaintEvent *event) override
{
QPainter painter(this);
// 设置画笔和画刷
QPen pen(Qt::black, 2);
painter.setPen(pen);
painter.setBrush(QBrush(Qt::green, Qt::SolidPattern));
// 定义矩形区域
QRect rect(50, 50, 200, 100);
// 设置圆角半径
qreal xRadius = 20;
qreal yRadius = 20;
// 绘制圆角矩形
painter.drawRoundedRect(rect, xRadius, yRadius, Qt::AbsoluteSize);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
RoundedRectWidget window;
window.resize(300, 200);
window.show();
return app.exec();
}
注意事项
-
圆角半径 (
xRadius
,yRadius
):xRadius
和yRadius
分别控制矩形的水平和垂直圆角半径。这两个值越大,圆角越圆润,矩形的边角越圆滑。- 如果
xRadius
和yRadius
的值太大,可能会导致矩形的边角接近圆形,甚至使矩形的某些部分消失。 - 选择合适的半径值以确保圆角矩形的视觉效果符合预期。
-
尺寸模式 (
Qt::SizeMode
):Qt::AbsoluteSize
:默认情况下,xRadius
和yRadius
是以绝对像素为单位的,这也是最常用的模式。Qt::RelativeSize
:在这种模式下,xRadius
和yRadius
是相对于矩形尺寸的比例。例如,xRadius = 0.1
表示圆角半径为矩形宽度的10%。- 根据需求选择合适的尺寸模式,通常使用
Qt::AbsoluteSize
以获得更精确的控制。
示例
void PaintWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置粗一点
QPen pen;
pen.setWidth(3);
painter.setPen(pen);
// 定义矩形区域
QRect rect(50, 50, 200, 100);
// 设置圆角半径
qreal xRadius = 20;
qreal yRadius = 20;
// 绘制圆角矩形
painter.drawRoundedRect(rect, xRadius, yRadius, Qt::AbsoluteSize);
// 下移200个像素
painter.translate(0,200);
//这点不知道是什么问题,当将0.1,0.5调整到较大的数时,才有效果
painter.drawRoundedRect(rect,0.1,0.5,Qt::RelativeSize);
}