PDA

View Full Version : paint Rect sometimes missing one border



stella1016
19th January 2011, 10:04
I have a QGraphicsRectItem. In its paint() method:



painter->setPen(QPen(Qt::red, 1, Qt::SolidLine));
painter->setBrush(QBrush(Qt::gray, Qt::Dense4Pattern));
painter->drawRect(draw_rect);







QRectF Myclass::boundingRect() const
{
qreal adjust = 1.0;
QRectF result(m_rect.topLeft().rx() - adjust/2, m_rect.topLeft().ry() - adjust/2,
m_rect.width() + adjust, m_rect.height() + adjust);

return result;
}



Most of the time, the rectangle is painted correctly. But after resize, sometimes it will miss the red line boarder, for example the left-side edge is not painted.

I tried with following: doesn't work:



QRectF Myclass::boundingRect() const
{
qreal adjust = 1.0;
QRectF result(m_rect.topLeft().rx() - adjust, m_rect.topLeft().ry() - adjust,
m_rect.width() + adjust, m_rect.height() + adjust);

return result;
}


Any one know this problem?

high_flyer
19th January 2011, 13:39
I am not sure I follow on your code but if m_rect is supposed to be a sub-rect , and adjust is the marigne to the original rect, then I would expect the following:


QRectF Myclass::boundingRect() const
{
qreal adjust = 1.0;
QRectF result(m_rect.topLeft().rx() + adjust, m_rect.topLeft().ry() + adjust,
m_rect.width() - adjust, m_rect.height() - adjust);

return result;
}

Otherwise it looks you want to draw a rect which is larger by 'adjust' to each direction of a given rect, if that is what you want, then I see nothing wrong in the code.

If you are scaling down (large to small) you might have a problem with the pen width, in that case you should set the pen width to 0.

stella1016
19th January 2011, 14:55
I am not sure I follow on your code but if m_rect is supposed to be a sub-rect , and adjust is the marigne to the original rect, then I would expect the following:


QRectF Myclass::boundingRect() const
{
qreal adjust = 1.0;
QRectF result(m_rect.topLeft().rx() + adjust, m_rect.topLeft().ry() + adjust,
m_rect.width() - adjust, m_rect.height() - adjust);

return result;
}

Otherwise it looks you want to draw a rect which is larger by 'adjust' to each direction of a given rect, if that is what you want, then I see nothing wrong in the code.

If you are scaling down (large to small) you might have a problem with the pen width, in that case you should set the pen width to 0.

Yes, I add the adjust of 1.0, since the pen width is 1. The actual QGraphicsRectItem has the m_rect set as its rectangle.

I tested it also with setting pen, and set adjust with half-size of pen width:


//in boundingRect()
qreal adjust = pen().widthF();
QRectF result(m_rect.topLeft().rx() - adjust/2.0, m_rect.topLeft().ry() - adjust/2.0,
m_rect.width() + adjust, m_rect.height() + adjust);



This is one of the example of qt documentation of boundingRect like follows:


QRectF CircleItem::boundingRect() const
{
qreal penWidth = 1;
return QRectF(-radius - penWidth / 2, -radius - penWidth / 2,
diameter + penWidth, diameter + penWidth);
}


Added after 4 minutes:

http://imageupload.org/?di=1112954474189

The problem can hanppen in any of these rectangle and any side during resize. But after again resize one pixel larger or smaller, the border shows again. I am not sure in painting, whether the floating point is rounded.

MarekR22
19th January 2011, 16:29
Most of the time, the rectangle is painted correctly. But after resize, sometimes it will miss the red line boarder, for example the left-side edge is not painted.
Resize is the problem. When you resize graphics item and it has impact on boundingRect you have to call: QGraphicsItem::prepareGeometryChange (not inside boundingRect), see also QGraphicsItem::boundingRect.

MarekR22
20th January 2011, 07:50
More or less it should look like this:

QRectF Myclass::boundingRect() const
{
static const qreal Adjust = 0.5;

return m_rect.adjusted(-Adjust, -Adjust, Adjust, Adjust);
}

QRectF Myclass::setSize(const QSizeF &newSize)
{
if (m_rect.size()==newSize) {
return;
}
m_rect.setSize(newSize);

prepareGeometryChange();
update();
}

QRectF Myclass::setTopLeft(const QPointF &newPosition)
{
if (m_rect.topLeft()==newPosition) {
return;
}
m_rect.setTopLeft(newPosition);

prepareGeometryChange();
update();
}
I don't now how did you do this class so most probably it will look a bit differently.

Stef
20th January 2011, 19:39
My suspicion is that this is due to a round off error. Adjust is a real. In the bounding rectangle calculation you divide this by 2, which is an integer. This causes the result also to be of type integer (thus, causing rounding errors). You can avoid this by dividing by 2.0.



QRectF Myclass::boundingRect() const
{
qreal adjust = 1.0;
QRectF result(m_rect.topLeft().rx() - adjust/2, m_rect.topLeft().ry() - adjust/2,
m_rect.width() + adjust, m_rect.height() + adjust);

return result;
}

Should be:



QRectF Myclass::boundingRect() const
{
qreal adjust = 1.0;
QRectF result(m_rect.topLeft().rx() - adjust/2.0, m_rect.topLeft().ry() - adjust/2.0,
m_rect.width() + adjust, m_rect.height() + adjust);

return result;
}