简体   繁体   中英

Drawn custom items sometimes chopped off in QGraphicsScene

I have a custom graphics item, that is inherting from QGraphicsEllipseItem . Specifically, my custom item is just a circle with a label attached to it (let me call it a "vertex"). I understand the idea: inherit from the base class, implement certain methods, and you are done.

The header is here:

#ifndef VERTEX_H
#define VERTEX_H

#include <QPointF>
#include <QGraphicsEllipseItem>

class Vertex : public QGraphicsEllipseItem
{
public:
    Vertex(const QPointF& pos, int label, int size = 20) : pos_(pos), label_(label), size_(size)  { }

    QRectF boundingRect() const;

protected:
    virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);

private:
    QPointF pos_;
    int label_;
    int size_;
};

#endif // VERTEX_H

The implementations here:

// vertex.cpp
#include "vertex.h"
#include <QPainter>

QRectF Vertex::boundingRect() const
{
    return QGraphicsEllipseItem(pos_.x(), pos_.y(), size_, size_).boundingRect();
}

void Vertex::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    painter->drawEllipse(pos_, size_, size_);
    painter->drawText(pos_, QString::number(label_));
}

Because my object really is an ellipse, I'd like to exploit the bounding rectangle implementation in an ellipse. However, something seems to be off when I draw things. In particular, I might see something like this:

在此处输入图片说明

(The above is cropped from a QGraphicsScene).

  1. Is my implementation for boundingRect off?
  2. Is something else causing "bad" drawing? I draw a Vertex when the user clicks the QGraphicsScene, so the QPointF argument to the constructor of Vertex is provided from mouseEvent->scenePos(); , where mouseEvent is of type QGraphicsSceneMouseEvent* .

First of all, you don't gain anything form and don't really need to inherit QGraphicsEllipseItem , it is better to start on a clean slate, just inherit QGraphicsItem . The stock ellipse item doesn't draw the ellipse from a center point and radius, so its bounding rect implementation will not match what you are drawing.

Since you essentially draw a circle with a center and radius, your correct bounding rect implementation should return a QRectF(pos_.x() - size_ / 2, pos.y() - size_ /2, size_, size_) .

Your current implementation doesn't return a rectangle which covers your item, instead it begins at its center and goes far outside:

在此处输入图片说明

OK, a little more help:

  • distinguish between absolute and relative coordinates - the point that comes from your mouse click will not actually be used to set the center of the circle, but the position of the graphics item
  • the circle's center will actually be relative to the item, so it will be QPointF(radius, radius) , in your case half of size_
  • you don't really need to store the center point
  • if your bounding rectangle implementation is correct everything will draw correctly
  • if you want the items to overlap, you will have to set a brush for the painter, otherwise it will only draw the outline of the circle

So creating a circle at the desired position and diameter and drawing it boils down to something like this:

class Circle : public QGraphicsItem {
public:
    Circle(QPointF c, int r) {
        setPos(QPointF(c.x() - r, c.y() - r));
        radius = r;
    }
    QRectF boundingRect() const { return QRectF(pos(), pos() + QPointF(radius * 2, radius * 2)); }
    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0) {
        painter->setBrush(Qt::white);
        painter->drawEllipse(boundingRect());
        painter->drawText(boundingRect().center(), "C");
    }
private:
    int radius;
};

And it all draws correctly now:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM