Drawing Polygonal Shapes in Qt GUI with QPainterPath::addPolygon()
Purpose
- The
QPainterPath::addPolygon()
function in Qt's GUI framework allows you to create a polygonal shape within aQPainterPath
object. This path can then be used for various drawing operations, such as filling or outlining the polygon.
Key Points
- Customization
You can further customize how the polygon is drawn by:- Setting the fill rule using
setFillRule()
(e.g.,Qt::OddEvenFill
orQt::WindingFill
) to determine how enclosed areas are filled. - Using a
QPainter
object and its methods likefillPath()
orstrokePath()
to fill or outline the polygon based on the path.
- Setting the fill rule using
- Subpath Creation
It adds an unclosed subpath to the currentQPainterPath
. This means that the line segments will be drawn from one vertex to the next, but the path won't automatically connect back to the starting point to form a closed shape. - Input
It takes aQPolygon
object as an argument, which defines the vertices (points) that make up the polygon.
Example
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QPolygon>
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
// Create a polygon with vertices
QPolygon polygon;
polygon << QPoint(50, 50);
polygon << QPoint(150, 100);
polygon << QPoint(100, 150);
// Add the polygon to the painter path
QPainterPath path;
path.addPolygon(polygon);
// Set the fill rule (optional)
path.setFillRule(Qt::OddEvenFill);
// Fill the polygon with a blue color
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(Qt::blue));
painter.fillPath(path, QBrush(Qt::blue));
// Optionally, outline the polygon with a black pen
// painter.setPen(QPen(Qt::black));
// painter.strokePath(path, QPen(Qt::black));
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
In this example:
- We create a
QPolygon
object with three vertices. - We create a
QPainterPath
object. - We call
addPolygon()
on the path, passing the polygon object. - We optionally set the fill rule.
- We use a
QPainter
object to fill the polygon with a blue brush. - (Optional) We could also use
strokePath()
to draw an outline around the polygon.
- It's particularly useful for creating complex shapes that can't be easily achieved with built-in shapes like rectangles or ellipses.
- When you need to draw a custom polygonal shape in your Qt GUI application.
Drawing a Star
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QPolygon>
#include <cmath>
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
// Calculate points for a five-pointed star
int numPoints = 5;
double outerRadius = 50;
double innerRadius = outerRadius * 0.382;
QPolygon polygon;
for (int i = 0; i < 2 * numPoints; ++i) {
double angle = 2 * M_PI * i / (2 * numPoints);
double radius = (i % 2 == 0) ? outerRadius : innerRadius;
polygon << QPoint(radius * cos(angle) + width() / 2,
radius * sin(angle) + height() / 2);
}
// Add the polygon to the path and fill it with yellow
QPainterPath path;
path.addPolygon(polygon);
painter.setBrush(QColor(Qt::yellow));
painter.fillPath(path, QBrush(Qt::yellow));
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
This code creates a pentagon with alternating larger and smaller points to form a star shape.
Drawing an Arrow
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QPolygon>
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
// Create a polygon for the arrow head and body
QPolygon head, body;
head << QPoint(0, 0) << QPoint(10, 5) << QPoint(5, 0);
body << QPoint(0, 0) << QPoint(20, 0) << QPoint(15, 5);
// Move and combine head and body polygons
QTransform transform;
transform.translate(width() / 2, height() / 2);
head = transform.map(head);
body = transform.map(body);
QPolygon arrow;
arrow << body.at(0) << body.at(1) << head.at(1) << head.at(2) << head.at(0) << body.at(2);
// Add the polygon to the path and stroke it with black
QPainterPath path;
path.addPolygon(arrow);
painter.setPen(QPen(Qt::black, 2));
painter.strokePath(path, QPen(Qt::black, 2));
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
This code creates two separate polygons, one for the arrow head and one for the body. It then combines them into a single polygon representing the entire arrow and strokes the path with a black pen.
Using Built-in Shapes
- Qt provides built-in classes for common shapes like rectangles (
QRect
), ellipses (QRectF
), and lines (QLine
). These can be more efficient for simple shapes and offer properties for customization (e.g., size, position, color).
#include <QApplication>
#include <QWidget>
#include <QPainter>
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
// Draw a rectangle with rounded corners
painter.setBrush(QColor(Qt::lightgray));
painter.setPen(QPen(Qt::black));
painter.drawRoundedRect(QRect(50, 50, 100, 70), 15, 15);
// Draw an ellipse with a blue outline
painter.setBrush(Qt::NoBrush);
painter.setPen(QPen(Qt::blue, 2));
painter.drawEllipse(QRectF(170, 30, 80, 120));
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
QPainter::drawConvexPolygon()
- If you have a convex polygon (all angles turn in the same direction), you can use
QPainter::drawConvexPolygon()
. This method can be slightly more efficient for convex shapes compared toQPainterPath::addPolygon()
.
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QPolygon>
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
// Create a convex polygon
QPolygon polygon;
polygon << QPoint(30, 50) << QPoint(100, 10) << QPoint(170, 80);
// Fill the polygon with green
painter.setBrush(QColor(Qt::green));
painter.setPen(Qt::NoPen);
painter.drawConvexPolygon(polygon);
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
Custom Drawing with QPainter
- For maximum flexibility, you can directly use the drawing methods of
QPainter
likedrawLine()
,drawArc()
, anddrawBezierCurve()
to construct your shapes. This approach requires more code but gives you complete control over every aspect of the drawing process.
Consider these factors when choosing an alternative:
- Control
Custom drawing withQPainter
provides the most control but requires more coding effort. - Performance
For simple convex shapes,QPainter::drawConvexPolygon()
might be slightly faster. - Shape Complexity
Built-in shapes are ideal for simple geometries.QPainterPath::addPolygon()
offers more flexibility for complex shapes.