ItemClipsToShape doesn't work
-
Hi,
I have a custom QGraphicsItem class that paints some complexes figures into scene. I have re-implemented boudingRect() member in order to make suitable "click and drag" on these kind of items. But a QRectF is not enough accurate for the precision that I need in clicks.
In my QGraphicsItem custom class I have the following sentences:
@
this->setFlag(QGraphicsItem::ItemClipsToShape, true);
this->setFlag(QGraphicsItem::ItemIsMovable, true);
@As I understand, ItemClipsToShape flag should replace the call "boundingRect()" to check if item has been clicked, for "shape" (that returns a QPaintPath) with the shape where I want to detect the click.
Shape has been implemented correctly, to check it, I draw it and It's properly drawn in scene:
@
QPainterPath path = shape();
painter->drawPath(path); //Properly drawn.
@The problem: it seems like Qt is still calling "boundingRect()" to get the area that I want to use to check if item is clicked, even with the flag set.
Any suggestions?
-
sry, but reading your post the following is not clear to me: did you reimplement QGraphicsItem::shape() in your graphicsitem subclass?
-
can you please post the code of the shape() and paint() method
-
Sure:
It returns the shape. Its a bit complicated method. Some lines build the entire item:
@
QPainterPath Cable::shape() const
QPainterPath result;
QLineF checkingLine(QPointF(0, 0), QPointF (1, 0));
foreach (CableLine* course, lines){
QLineF current(course->posx, course->posy);
if (current.angleTo(checkingLine) == 0 || current.angleTo(checkingLine) == 180){
QPointF init(current.p1().x(), current.p1().y() - 3);
QPointF ending(current.p2().x(), current.p2().y() + 3);
QRectF rect(init, ending);
result.addRect(rect);
continue;
}
if (current.angleTo(checkingLine) == 90 || current.angleTo(checkingLine) == 270){
QPointF init(current.p1().x() - 3, current.p1().y());
QPointF ending(current.p2().x() + 3, current.p2().y());
QRectF rect(init, ending);
result.addRect(rect);
continue;
}
qDebug() << "Error condition";
}
result.setFillRule(Qt::OddEvenFill);
return result;
}
@And paint:
@
void Cable::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{if (!painter) return; painter->save(); //Draw connection arrow: QVector <QPointF> polyPoints; CableLine* line = lines.last(); QLineF last(line->posx, line->posy); polyPoints.append(QPointF(last.x2() - _ARROW_CABLE_WIDTH/2, last.y2())); polyPoints.append(QPointF(last.x2() + _ARROW_CABLE_WIDTH/2, last.y2())); polyPoints.append(QPointF(last.x2(), last.y2() + _ARROW_CABLE_HEIGHT)); QPolygonF poly(polyPoints); painter->drawPolygon(poly); painter->restore();
}
@ -
are you sure you want to use Qt::OddEvenFill fill rule instead of Qt::WindingFill ?
Nevertheless i couldn't spot any problem in your code on first glance.But whats exactly the problem? That boundingRect() is called at all? Or that you receive mouse events even outside the shape?
-
No. The problem is that I want to use shape() instead boundingRect() in order to captura click events.
I tried with Qt::WindingFill, with the same resutl, and I setted this->setFlag(QGraphicsItem::ItemClipsToShape, true).
Even so, click event is only called inside the boundingRect() rectangle, but It's not the exactly area that I want the item to reply to such event. It's the shape area intead.
Shape area is correctly, because when I draw it in paint method, I can see correctly filled and drawn.
Thank you for you reply.
-
I have some troubles with mapTo.
When shapes colliding, I enter a function: "collisionProduced". But, by calling mapToScene, the shape seems being displaced to left. How it comes? I just changed the coordinate system in order to obtain the coords in scene system, not moving the shape.
-
I had same problem. My item is a circle icon, the boundingRect is a square. Clicks within the square but outside the circle area triggers mouse events. I fixed it by defining shape() as constant method, which overrides the parent::shape() const instead of overloading another shape().
@
QPainterPath shape() const;
@