Time for action – Creating a graphics item class

Ask Qt Creator to add a new C++ class to the project. Input SineItem as the class name, leave <Custom> in the Base class drop-down list, and input QGraphicsItem in the field below it. Finish the wizard and open the created sineitem.h file.

Set the text cursor inside QGraphicsItem in the class declaration and press Alt + Enter. At first; Qt Creator will suggest that you Add #include <QGraphicsItem>. Confirm that and press Alt + Enter on QGraphicsItem again. Now, Qt Creator should suggest that you select Insert Virtual Functions of Base Classes. When you select this option, a special dialog will appear:

The function list contains all virtual functions of the base class. The pure virtual functions (which must be implemented if you want to create objects of the class) are enabled by default. Check that everything is set as in the preceding screenshot, and then click on OK. This convenient operation adds declaration and implementation of the selected virtual functions to the source files of our class. You can write them manually instead, if you want.

Let's edit sineitem.cpp to implement the two pure virtual functions. First of all, a couple of constants at the top of the file:

static const float DX = 1;
static const float MAX_X = 50;

In our graph, x will vary from 0 to MAX_X, and DX will be the difference between the two consequent points of the graph. As you may know, sin(x) can have values from -1 to 1. This information is enough to implement the boundingRect() function:

QRectF SineItem::boundingRect() const
{
    return QRectF(0, -1, MAX_X, 2);
}

This function simply returns the same rectangle every time. In this rectangle, x changes from 0 to MAX_X, and y changes from -1 to 1. This returned rectangle is a promise to the scene that the item will only paint in this area. The scene relies on the correctness of that information, so you should strictly obey that promise. Otherwise, the scene will become cluttered up with relics of your drawing!

Now, implement the paint() function, as follows:

void SineItem::paint(QPainter *painter, 
const QStyleOptionGraphicsItem *option, QWidget *widget) { QPen pen; pen.setCosmetic(true); painter->setPen(pen); const int steps = qRound(MAX_X / DX); QPointF previousPoint(0, sin(0)); for(int i = 1; i < steps; ++i) { const float x = DX * i; QPointF point(x, sin(x)); painter->drawLine(previousPoint, point); previousPoint = point; } Q_UNUSED(option) Q_UNUSED(widget) }

Add #include <QtMath> to the top section of the file to make math functions available.