Solved Discrepancy between drawRect and drawLine
-
Hello,
I am seeing a little discrepancy between drawing the same QRectF with drawRect and drawing the individual sides using four drawLine's.
Take this QRectF for example:
QRectF rect(44.81574989,0 45.01417423x18.2834643)
Drawing it with:
painter->fillRect(rect, QBrush(colorBackground));
or with:
painter->drawRect(rect);
Gives different results to this:
painter->drawLine(rect.topLeft().x(), rect.topLeft().y(), rect.topRight().x(), rect.topRight().y()); painter->drawLine(rect.topRight().x(), rect.topRight().y(), rect.bottomRight().x(), rect.bottomRight().y()); painter->drawLine(rect.bottomRight().x(), rect.bottomRight().y(), rect.bottomLeft().x(), rect.bottomLeft().y()); painter->drawLine(rect.bottomLeft().x(), rect.bottomLeft().y(), rect.topLeft().x(), rect.topLeft().y());
Here's the result:
There should not be any white space inside that square, nor should it overflow on the right. Can someone advise please?
-
I think you are seeing the results of:
A filled rectangle has a size of rectangle.size(). A stroked rectangle has a size of rectangle.size() plus the pen width.
https://doc.qt.io/qt-5/qpainter.html#drawRect
In addition, it might be the result of the overloads you have used: you are drawing lines using integer coordinates, but you draw the rectangle using qreal coordinates. There may be differences in rounding and in effect it has on antialiasing.
-
@sierdzio Thank you for this!
I double checked, the .x() and .y() functions do return a qreal. The error would have been significantly larger in my coordinate system if these were int.
Both drawRect and fillRect draw over the same area which doesn't match the drawLine area.
If this really was the effect of the extra QPen border around the rectangle, it would have shown up in the Y axis as well. Besides, I did make sure the pen width was set to zero and that's not it.
Adam
-
@Adam-Crowe said in Discrepancy between drawRect and drawLine:
@sierdzio Thank you for this!
I double checked, the .x() and .y() functions do return a qreal. The error would have been significantly larger in my coordinate system if these were int.
You've double-checked the wrong end ;-) It's the
drawLine()
which takesint
s, conversion is implicit.Both drawRect and fillRect draw over the same area which doesn't match the drawLine area.
If this really was the effect of the extra QPen border around the rectangle, it would have shown up in the Y axis as well. Besides, I did make sure the pen width was set to zero and that's not it.
Good point. Additionally, see this: https://doc.qt.io/qt-5/qrectf.html#rendering and https://doc.qt.io/qt-5/qpen.html#setWidth
A line width of zero indicates a cosmetic pen. This means that the pen width is always drawn one pixel wide, [...]
I still think it does not explain why
x()
has a shift whiley()
does not, but maybe it will point you in the right direction. -
@sierdzio Shocking 😳
So there's really no way to fill a rectangle without a 1 pixel overflow on the right hand side? My coordinate system represents real world millimetres and gets scaled up on the screen based on the screen's DPI. Accuracy is absolutely paramount. On Windows using .Net, this stuff is trivial because GDI+ does all the conversions for you, but it's been a hell of a challenge with Qt's QPainter to achieve this.
Do you think QPainter::drawLines(const QVector<QLineF> &lines) would round to an int also?
Adam
-
@Adam-Crowe said in Discrepancy between drawRect and drawLine:
So there's really no way to fill a rectangle without a 1 pixel overflow on the right hand side?
Use fillRect(), it won't have any border and thus should not be shifted. I hope ;-)
-
@sierdzio YOU WERE SO RIGHT! It was the drawLine that was wrong and not the drawRect or fillRect.
Once I definite a QLineF line(…) for that line and did a drawLine(line) everything fell right into place!
Incredible. Thank you so much!!!
Adam
-
Oh wow, it was just a guess :D OK, I'm glad this is solved. Happy coding!