Time for action – Using child items
Let's try to make an item containing multiple children. We want to create a rectangle with a filled circle in each corner and be able to move and rotate it as a whole, like this:
First, you need to create a function that creates a single complex rectangle, by using the following code:
QGraphicsRectItem *createComplexItem(
qreal width, qreal height, qreal radius)
{ QRectF rect(-width / 2, -height / 2, width, height); QGraphicsRectItem *parent = new QGraphicsRectItem(rect); QRectF circleBoundary(-radius, -radius, 2 * radius, 2 * radius); for(int i = 0; i < 4; i++) { QGraphicsEllipseItem *child = new QGraphicsEllipseItem(circleBoundary, parent); child->setBrush(Qt::black); QPointF pos; switch(i) { case 0: pos = rect.topLeft(); break; case 1: pos = rect.bottomLeft(); break; case 2: pos = rect.topRight(); break; case 3: pos = rect.bottomRight(); break; } child->setPos(pos); } return parent; }
We start with creating a QRectF variable that contains the rectangle coordinates in the item's coordinate system. Following the tip we provided earlier, we create a rectangle centered at the origin point. Next, we create a rectangle graphics item called parent, as usual. The circleBoundary rectangle is set to contain the boundary rect of a single circle (again, the center is at the origin point). When we create a new QGraphicsEllipseItem for each corner, we pass parent to the constructor, so the new circle item is automatically added as a child of the rectangle item.
To set up a child circle, we first use the setBrush() function that enables filling of the circle. This function expects a QBrush object that allows you to specify an advanced filling style, but in our simple case, we use an implicit conversion from the Qt::GlobalColor enum to QBrush. You will learn more about brushes later in this chapter.
Next, we select a different corner of the rectangle for each circle and call setPos() to move the circle to that corner. Finally, we return the parent item to the caller.
You can use this function as follows:
QGraphicsRectItem *item1 = createComplexItem(100, 60, 8); scene.addItem(item1); QGraphicsRectItem *item2 = createComplexItem(100, 60, 8); scene.addItem(item2); item2->setPos(200, 0); item2->setRotation(20);
Note that when you call setPos(), the circles are moved along with the parent item, but the pos() values of the circles do not change. This is the consequence of the fact that pos() means the position relative to the parent item (or the scene's origin, if there is no parent item). When the rectangle is rotated, circles rotate with it, as if they were fixed to the corners. If the circles weren't children of the rectangle, positioning them properly, in this case, would be a more challenging task.