Bounding Box Shape Adjustment

I draw a line using the mouse. The string is drawn using the draw function as:

painter->drawLine(start_p, end_p); 

The line bounding box is defined as:

 QRectF Line::boundingRect() const { // bounding rectangle for line return QRectF(start_p, end_p).normalized(); } 

enter image description here

It shows the line colored. I get a bounding box for this, as shown:

enter image description here

I want to have a bounding box according to the shape of the element, something like: enter image description here

How to do it?

Edit

When you select any of the overlapping lines, one with the bounding box at the top is selected (see figure below). Even using setZValue will not work here. I want to implement this by minimizing the bounding rectangle to the line shape.

enter image description here

+6
source share
4 answers

If you have an element that does not have a rectangle shape or is a rotating rectangle, use QGraphicsItem::shape .

This function should return QPainterPath . You must create your path using QPainterPath::addPolygon .

Here is a small example:

 QPainterPath Item::shape() const { QPainterPath path; QPolygon polygon; polygon << QPoint(0, 0); polygon << QPoint(5, 5); polygon << QPoint(width, height); polygon << QPoint(width - 5, height - 5); path.addPolygon(polygon); return path; } 

Of course, you must calculate your points within the path differently, but you understand the point. Now, when you click on an element, it will select it only if the click occurred inside the form defined by QPainterPath .

If you ever need to make curvy lines, you can use QPainterPathStroker::createStroke , as suggested by cmannett85.

+6
source

QGraphicsItem has two related functions that you are interested in. The first is boundingRect . This, as you probably understand, is a rectangle that spans the entire element. Qt uses this for things like quick calculation of how much of an element is visible and a simple collision of elements.

Great if you have rectangular elements; you can simply override boundingRect () on any elements that you inherit from QGraphicsItem or QGraphicsObject.

If you have a form that is not regular, and you want to do things like colliding with the shape of an element, then the shape () function also requires an override in your class.

This returns QPainterPath, so you can do something like this: -

 QPainterPath Line::shape() { QRectF rect(start_p, end_p).normalized(); // increase the rect beyond the width of the line rect.adjust(-2, -2, 2, 2); QPainterPath path; path.addRect(rect); return path; // return the item defined shape } 

Now you can use the painter to draw the shape () element, instead of boundingRect (), and collisions will work as expected.

+1
source

boundingRect always used to optimize the process of drawing a scene. Thus, you have no room for manipulation here.

BUT , if you want to change the area of ​​interaction with the mouse, the shape method . By default, this method returns the QPainterPath rectangle obtained from the boundingRect method.
Therefore, simply override this method and provide the desired form.

 QPainterPath YourGraphicsItem::shape() const { static const qreal kClickTolerance = 10; QPointF vec = end_p-start_p; vec = vec*(kClickTolerance/qSqrt(QPointF::dotProduct(vec, vec))); QPointF orthogonal(vec.y(), -vec.x()); QPainterPath result(start_p-vec+orthogonal); result.lineTo(start_p-vec-orthogonal); result.lineTo(end_p+vec-orthogonal); result.lineTo(end_p+vec+orthogonal); result.closeSubpath(); return result; } 
+1
source

You have to draw yourself limited if you want something like that. let Qt have a QRect to constrain and define your new QRect, depending on the angle of the previous QRect, upper left and lower right. for example, if the upper left corner is (2.2), your new left QRect (1.2) and the upper right (2.1) and ....

-1
source

Source: https://habr.com/ru/post/976472/


All Articles