Drawing basic shapes on screen

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.

How to do it…

First, let's create a new Qt Widgets Application project:

  1. Open up 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:
    How to do it…
  2. Then, open up mainwindow.h and add the following code to include the QPainter header file:
    #include <QMainWindow>
    #include <QPainter>
    
  3. Then, declare the paintEvent() event handler below the class destructor:
    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    virtual void paintEvent(QPaintEvent *event);
    
  4. Next, open up mainwindow.cpp and define the paintEvent() event handler:
    void MainWindow::paintEvent(QPaintEvent *event)
    {
    }
  5. After that, we will add text to the screen using the 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");
  6. Then, we will draw a straight line that starts from (50, 60) and ends at (100, 100):
    QPainter linePainter(this);
    linePainter.drawLine(QPoint(50, 60), QPoint(100, 100));
  7. We can also easily draw a rectangle shape by calling the 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));
  8. Next, declare a 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);
  9. We can also use 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);
  10. You can also draw any other shapes by using 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);
  11. 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);
  12. The final result should look something like this:
    How to do it…

How it works...

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.

There's more…

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.44.143