Qt 2D drawing: draw text, path, image, composite mode

1. Draw text

In addition to drawing graphics, you can also use the QPainter::darwText() function to draw text, or use QPainter::setFont() to set the font used by the text, and use the QPainter::fontInfo() function to obtain font information, which returns a QFontInfo class object. Antialiasing is used by default when drawing text.

1.1 Basic drawing

The code demonstration is still performed in the program in the previous section, and the content of paintEvent() is changed as follows:

void Widget::paintEvent(QPaintEvent *)
{    
      QPainter painter(this);    
      painter.drawText(100, 100,  "qter.org-yafeilinux");
}

This draws a string at position (100, 100). Results as shown below.

 The benefits of this article, the fee to receive Qt development learning materials package, technical video, content includes (C++ language foundation, Qt programming introduction, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project combat, QSS, OpenCV, Quick module, interview questions, etc.) ↓↓↓↓↓↓ See below

1.2 Control text position

We first go to the help documentation page of QPainter, then look at the overloaded form of the drawText() function and find:

QPainter::drawText ( const QRectF & rectangle, int flags, const QString & text, QRectF * boundingRect = 0 )
  • The first parameter specifies the rectangle where the text is drawn;
  • The second parameter specifies the alignment of the text in the rectangle, which is defined by the Qt::AlignmentFlag enumeration type. Different alignments can also be used at the same time using the "|" operator. Other flags defined by Qt::TextFlag can also be used here, such as automatic line wrapping, etc.;
  • The third parameter is the text to be drawn, here you can use "\n" to achieve line break;
  • The fourth parameter generally does not need to be set.

Let's look at an example. In order to more clearly see the position of the text in the specified rectangle, we draw this rectangle. Change the paintEvent() function as follows:

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    //设置一个矩形
    QRectF rect(50, 50, 300, 200);
    //为了更直观地看到字体的位置,我们绘制出这个矩形
    painter.drawRect(rect);
    painter.setPen(QColor(Qt::red));
    //这里先让字体水平居中
    painter.drawText(rect, Qt::AlignHCenter, "yafeilinux");
}

Now run the program, the effect is shown in the figure below.

 

The available alignments are shown in the image below.

 

1.3 Using fonts

In order to draw beautiful text, you can use the QFont class to set the text font. You can also check the introduction of this class in the help documentation first. Some of the most commonly used settings are demonstrated below.

Change the paintEvent() function as follows:

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    //设置一个矩形
    QRectF rect(50, 50, 300, 200);
    //为了更直观地看到字体的位置,我们绘制出这个矩形
    painter.drawRect(rect);
    painter.setPen(QColor(Qt::red));
    //这里先让字体水平居中
    painter.drawText(rect, Qt::AlignHCenter, "yafeilinux");

    //使用字体
    QFont font("宋体", 15, QFont::Bold, true);
    //设置下划线
    font.setUnderline(true);
    //设置上划线
    font.setOverline(true);
    //设置字母大小写
    font.setCapitalization(QFont::SmallCaps);
    //设置字符间的间距
    font.setLetterSpacing(QFont::AbsoluteSpacing, 10);
    //使用字体
    painter.setFont(font);
    painter.setPen(Qt::blue);
    painter.drawText(120, 80, tr("yafeilinux"));
    painter.translate(50, 50);
    painter.rotate(90);
    painter.drawText(0, 0, tr("helloqt"));
}

A QFont font object is created here, the constructor used is QFont::QFont ( const QString & family, int pointSize = -1, int weight = -1, bool italic = false ), the first parameter sets the family attribute of the font, the font family used here is Song, you can use the QFontDatabase class to obtain all supported fonts; the second parameter is the point size, the default size is 12; the third parameter is the weight attribute, which is used here bold; the last property sets whether to use italics. Then we use several other functions to format the font, and finally call the setFont() function to use the font, and use another overloaded form of the drawText() function to draw the text at point (120, 80). Later, the coordinate system was translated and rotated, and then the text was drawn again. Run the program, the effect is shown in the figure below.

 

2. Draw the path

If you want to draw a complex graphic, you can use the QPainterPath class, and then use QPainter::drawPath() to draw. The QPainterPath class provides a container for drawing operations that can be used to create graphics and reuse them. A drawing path is an object composed of multiple rectangles, ellipses, lines, or curves. A path can be closed, such as rectangles and ellipses, or unclosed, such as lines and curves.

2.1 Simple application

Let's look at an example: add an ellipse and a line in the graphics path. Still explained in the previous project. Change the paintEvent() function as follows:

void Widget::paintEvent(QPaintEvent *)
{
    //添加一个椭圆和一根线在图形路径里
    QPainterPath path;
    path.addEllipse(100, 100, 50, 50); //添加一个圆心为(100,100),横纵半径都为50的椭圆
    path.lineTo(200, 200); //添加一根从当前位置到(200,200)的线
    QPainter painter(this);
    painter.setPen(Qt::blue);
    painter.setBrush(Qt::red);
    painter.drawPath(path);
}

After creating a QPainterPath object, you can use functions such as lineTo(), arcTo(), cubicTo(), and quadTo() to add lines or curves to the path. Run the program, the effect is shown in the figure below.

 

2.2 Copy graphics

If you simply stitch several graphics together, there is no need to use paths at all. The reason why paths are introduced is because of a very useful function: copy graphics paths. Change the paintEvent() function as follows:

void Widget::paintEvent(QPaintEvent *)
{
    //添加一个椭圆和一根线在路径里
    QPainterPath path;
    path.addEllipse(100, 100, 50, 50); //添加一个圆心为(100,100),横纵半径都为50的椭圆
    path.lineTo(200, 200); //添加一根从当前位置到(200,200)的线
    QPainter painter(this);
    painter.setPen(Qt::blue);
    painter.setBrush(Qt::red);
    painter.drawPath(path);

    //复制图形路径
    QPainterPath path2;
    path2.addPath(path);
    path2.translate(100,0);
    painter.drawPath(path2);
}

Now run the program, the effect is shown in the figure below.

 

It can be seen that for the already drawn path, it is very simple to repeat the drawing.

2.3 Current position when drawing graphics

Let's look at an example first, change the paintEvent() function as follows:

void Widget::paintEvent(QPaintEvent *)
{
    QPainterPath path;
    path.lineTo(100, 100);
    path.lineTo(200, 100);
    QPainter painter(this);
    painter.drawPath(path);
}

The running effect of the program is shown in the figure below.

 

It can be seen that after the path is created, the default is to draw from (0, 0) point. After the first straight line is drawn, the current position is (100, 100) point, and the second straight line is drawn from here. After drawing the second line, the current position is (200, 100).

We can also use the moveTo() function to change the position of the current point. For example, change the paintEvent() function as follows:

void Widget::paintEvent(QPaintEvent *)
{
    QPainterPath path;
    path.addRect(50, 50, 40, 40);

    //移动到(100, 100)点
    path.moveTo(100, 100);

    path.lineTo(200, 200);
    QPainter painter(this);
    painter.drawPath(path);
}

In this way, when the rectangle is drawn, it will move to the (100, 100) point for subsequent drawing. The program running effect is shown in the figure below

 

3. Draw pictures

Qt provides four classes to handle image data: QImage, QPixmap, QBitmap, and QPicture, which are commonly used drawing devices. Among them, QImage is mainly used for I/O processing, which optimizes I/O processing operations, and can be used to directly access and manipulate pixels; QPixmap is mainly used to display images on the screen, which optimizes images displayed on the screen; QBitmap is a subclass of QPixmap, which is used to process images with a color depth of 1, that is, only black and white colors can be displayed; QPicture is used to record and replay QPainter commands. In this section we only explain QPixmap.

3.1 Simple drawing of pictures

(1) This time we re-create a Qt Widgets application, the project name is mypixmap, on the class information page, select the base class as QDialog, and use the default Dialog as the class name.

(2) Then copy a picture in the source code directory, for example, here is a logo.png picture, as shown in the figure below.

 

(3) Add the declaration of the redraw event handler function in the dialog.h file:

protected:
    void paintEvent(QPaintEvent *);

(4) First add the header file to the dialog.cpp file to include #include <QPainter>, and then add the definition of the function:

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load("../mypixmap/logo.png");
    painter.drawPixmap(0, 0, 80, 100, pix);
}

A relative path is used here, because Qt Creator uses shadow build by default, that is, the compiled files are in a directory like build-mypixmap-Desktop_Qt_5_8_0_MinGW_32bit-Debug, and this directory is the current directory, so the source code directory is its parent directory. You can change the path according to your actual situation, or use an absolute path, but it is best to use resource files to store pictures. The drawPixmap() function draws a picture in a given rectangle, where the upper left corner of the rectangle is (0, 0), with a width of 80 and a height of 100. If the width and height are different from the size of the picture, the picture will be stretched by default. The running effect is shown in the figure below.

 

3.2 Pan image

The translate() function in the QPainter class realizes the change of the coordinate origin. After changing the origin, this point will become the new origin (0, 0). Let's look at an example. Continue to add the following code in the paintEvent() function:

//将(100,100)设为坐标原点
painter.translate(100, 100);
painter.drawPixmap(0, 0, 80, 100, pix);

Here, (100, 100) is set as the new coordinate origin, so the following texture at (0, 0) is equivalent to the previous (100, 100) texture. Run the program, the effect is shown in the figure below.

 

3.3 Zoom image

We can use the scaled() function in the QPixmap class to zoom in and out of the picture. Continue to add the following code in the paintEvent() function:

//获得以前图片的宽和高
qreal width = pix.width();
qreal height = pix.height();
//将图片的宽和高都缩小,并且在给定的矩形内保持宽高的比值不变
pix = pix.scaled(width, height,Qt::KeepAspectRatio);
painter.drawPixmap(90, 90, pix);

Among them, the parameter Qt::KeepAspectRatio is the way to zoom the image. You can place the mouse pointer on the code and press the F1 key to view its help, as shown in the figure below.

 

There are three values ​​here, which can be roughly understood by looking at the example picture. Qt::IgnoreAspectRatio does not maintain the aspect ratio of the image; Qt::KeepAspectRatio maintains the aspect ratio in a given rectangle; the last one also maintains the aspect ratio, but may exceed the given rectangle. The rectangle given here is determined by the parameters given when we display the picture, for example, painter.drawPixmap(0,0,100,100,pix); is in a rectangle whose width and height are both 100 starting from the (0,0) point. The effect of running the program is shown in the figure below.

 

3.4 Rotate picture

The rotation uses the rotate() function of the QPainter class, which rotates around the origin by default. If you want to change the center of rotation, you can use the translate() function mentioned earlier. Continue to add the following code in the paintEvent() function:

//让图片的中心作为旋转的中心
painter.translate(40, 50);
painter.rotate(90); //顺时针旋转90度
painter.translate(-40,-50); //使原点复原
painter.drawPixmap(100, 100, 80, 100, pix);

Here you must first change the center of rotation, then rotate, and then restore the origin to achieve the desired effect. Run the program, as shown in the figure below.

 

3.5 Distorting images

The distortion of the picture is accomplished by using the shear(qreal sh, qreal sv) function of the QPainter class. It has two parameters, the former parameter realizes horizontal deformation, and the latter parameter realizes longitudinal deformation. When their value is 0, it means no distortion. Continue to add the following code in paintEvent():

painter.shear(0.5, 0); //横向扭曲
painter.drawPixmap(100, 0, 80, 100, pix);

The running effect is shown in the figure below.

 

4. Composite mode

QPainter provides Composition Modes to define how to complete the composition of digital images, that is, how to combine the pixels of the source image and the pixels of the target image. The commonly used composite modes and their effects provided by QPainter are shown in the figure below. The common type is SoiirceOver (usually called alpha blending), that is, the source pixel being drawn is mixed on the target pixel that has been drawn, and the alpha component of the source pixel defines its transparency, so that the source image will be displayed on the target image with a transparent effect. When composite mode is set, it will be applied to all drawing operations, such as pen, brush, gradient and pixmap/image drawing, etc.

 

 

Example:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter;
    QImage image(400, 300, QImage::Format_ARGB32_Premultiplied);
    painter.begin(&image);
    painter.setBrush(Qt::green);
    painter.drawRect(100, 50, 200, 200);
    painter.setBrush(QColor(0, 0, 255, 150));
    painter.drawRect(50, 0, 100, 100);
    painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
    painter.drawRect(250, 0, 100, 100);
    painter.setCompositionMode(QPainter::CompositionMode_DestinationOver);
    painter.drawRect(50, 200, 100, 100);
    painter.setCompositionMode(QPainter::CompositionMode_Xor);
    painter.drawRect(250, 200, 100, 100);
    painter.end();
    painter.begin(this);
    painter.drawImage(0, 0, image);
}

Here, a rectangle is first drawn on Qlmage, and then 4 small rectangles are drawn at the 4 corners of the rectangle. Each small rectangle uses a different composite mode and is filled with a translucent color. The first small rectangle does not explicitly specify the composite mode, it uses the SourceOver mode by default. The running effect is shown in the figure below.

 

The article is transferred from the blog garden (fengMisaka): Qt 2D drawing three: drawing text, path, image, composite mode

The benefits of this article, the fee to receive Qt development learning materials package, technical video, content includes (C++ language foundation, Qt programming introduction, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project combat, QSS, OpenCV, Quick module, interview questions, etc.) ↓↓↓↓↓↓ See below

Guess you like

Origin blog.csdn.net/QtCompany/article/details/131838628