In this section, we will learn how to draw simple vector shapes (line, rectangle, circle, and so on) and display text on the main window using the QPainter
class. We will also learn how to change the drawing style of the vector shapes using the QPen
class.
First, let's create a new Qt Widgets Application project:
mainwindow.ui
and remove the menu bar, main tool bar, and status bar so that we get a clean, empty main window. Right-click on the bar widgets and select Remove Menu Bar from the pop-up menu:mainwindow.h
and add the following code to include the QPainter
header file:#include <QMainWindow>
#include <QPainter>
paintEvent()
event handler below the class destructor:public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
virtual void paintEvent(QPaintEvent *event);
mainwindow.cpp
and define the paintEvent()
event handler:void MainWindow::paintEvent(QPaintEvent *event) { }
QPainter
class inside the paintEvent()
event handler. We set the text font settings before drawing it on the screen at the position (20, 30)
:QPainter textPainter(this); textPainter.setFont(QFont("Times", 14, QFont::Bold)); textPainter.drawText(QPoint(20, 30), "Testing");
(50, 60)
and ends at (100, 100)
:QPainter linePainter(this); linePainter.drawLine(QPoint(50, 60), QPoint(100, 100));
drawRect()
function using a QPainter
class. This time however, we also apply a background pattern to the shape before drawing it:QPainter rectPainter(this); rectPainter.setBrush(Qt::BDiagPattern); rectPainter.drawRect(QRect(40, 120, 80, 30));
QPen
class, set its color to red
, and set its drawing style to Qt::DashDotLine
. Then, apply the QPen
class to QPainter
and draw an ellipse shape at (80, 200)
with a horizontal radius of 50
and a vertical radius of 20
:QPen ellipsePen; ellipsePen.setColor(Qt::red); ellipsePen.setStyle(Qt::DashDotLine); QPainter ellipsePainter(this); ellipsePainter.setPen(ellipsePen); ellipsePainter.drawEllipse(QPoint(80, 200), 50, 20);
QPainterPath
class to define a shape before passing it over to the QPainter
class for rendering:QPainterPath rectPath; rectPath.addRect(QRect(150, 20, 100, 50)); QPainter pathPainter(this); pathPainter.setPen(QPen(Qt::red, 1, Qt::DashDotLine, Qt::FlatCap, Qt::MiterJoin)); pathPainter.setBrush(Qt::yellow); pathPainter.drawPath(rectPath);
QPainterPath
, such as an ellipse:QPainterPath ellipsePath; ellipsePath.addEllipse(QPoint(200, 120), 50, 20); QPainter ellipsePathPainter(this); ellipsePathPainter.setPen(QPen(QColor(79, 106, 25), 5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); ellipsePathPainter.setBrush(QColor(122, 163, 39)); ellipsePathPainter.drawPath(ellipsePath);
QPainter
can also be used to draw an image file onto the screen. In the following example, we load an image file called tux.png
and draw it on the screen at position (100, 150)
:QImage image; image.load("tux.png"); QPainter imagePainter(this); imagePainter.drawImage(QPoint(100, 150), image);
If you want to draw something on screen using QPainter
, basically all you need to do is tell it what type of graphics it should be drawing (text, vector shape, image, polygon, and so on) with its position and size.
QPen determines what the outline of the graphic should look like, such as its color, line width, line style (solid, dashed, dotted, and so on), cap style, join style, and so on.
On the other hand, QBrush
sets the style of the background of the graphics, such as the background color, pattern (solid color, gradient, dense brush, crossing diagonal lines, and so on) and pixmap.
The options for the graphics should be set before calling the draw function (drawLine()
, drawRect()
, drawEllipse()
, and so on).
If your graphics do not appear on screen and you see warnings such as QPainter::setPen: Painter not active
and QPainter::setBrush: Painter not active
appearing on the application output window in Qt Creator, it means that the QPainter
class is not currently active and your program will not trigger its paint event. To solve this problem, set the main window as the parent of the QPainter
class. Usually, if you're writing code in the mainwindow.cpp
file, all you need to do is to put this
in the bracket when initializing QPainter
. For example:
QPainter linePainter(this);
QImage
can load images from both the computer directories and from the program resources.
Think of QPainter
as a robot with a pen and an empty canvas. You just have to tell the robot what type of shape it should be drawing and its location on the canvas, then the robot will do its job based on your description. To make your life easier, the QPainter
class also provides numerous functions such as drawArc()
, drawEllipse()
, drawLine()
, drawRect()
, drawPie()
, and so on that allow you to easily render a predefined shape.
In Qt, all the widget classes (including the main window) have an event handler called QWidget::paintEvent()
. This event handler will be triggered whenever the operating system thinks that the main window should re-draw its widgets. Many things can lead to that decision, such as the main window being scaled, a widget changing its state (that is, a button being pressed), or functions such as repaint()
or update()
being invoked manually in the code. Different operating system may behave differently when it comes to deciding whether or not to trigger the update event on the same set of conditions. If you're making a program that requires continuous and consistent graphical updates, call repaint()
or update()
manually with a timer.
13.58.51.36