Coordinate system issues in QPaint
-
Hi all, I'm a Qt beginner and met a problem when reading examples on QPaint. Here's the reimplemented paintEvent() code:
void painterTime::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); QPen pen(Qt::black); pen.setWidth(6); painter.setPen(pen); QRect r = rect().adjusted(10, 10, -10, -10); painter.drawRoundedRect(r, 20, 10); painter.save(); r.adjust(20, 20, -20, -20); painter.setViewport(r); r.moveTo(0, -r.height()/2); painter.setWindow(r); drawChart(&painter, r); painter.restore(); }
and the drawChart() member function is defined as follows:
void painterTime::drawChart(QPainter *painter, const QRect &rect) { painter->setPen(Qt::red); painter->drawLine(0, 0, rect.width(), 0); }
The resulting paint is:
Which is not what I'm expecting it to be.Since I suppose the origin of painter coordinate system to be the default origin of widget client region, namely the top-left corner of geometry(), the result should be something like this:
because in drawChart function, a line is drawn without clipping from the origin with a length of the width of the window and viewport, and in my opinion the origion of painter is the same as the device because I have not transformed it. To confirm my guess, I modified the code paint part:void painterTime::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); QPen pen(Qt::black); pen.setWidth(6); painter.setPen(pen); int w = rect().width(); int h = rect().height(); painter.setWindow(0, -h/2, w, h); painter.setViewport(w/4, h/4, w/2, h/2); painter.drawRect(0, -h/2, w, h); }
It draws as expected and confirms my guesss that painter coordinate system is the same as that of the device:
My logic is deducted as follows:
So I got a contradiction.My question is what actually is the coordinate system and origin of QPainter instance? How to explain this contradiction I got? If you have any question about my statement, please leave a comment! Any help will be greatly appreciated!
-
Hi! The image-upload feature on our forum is broken, you might see the picture but other users don't. Please upload your image to a image hoster of your choice (e.g. postimage.org) and embed the pic here with the following markup:

.See also How to insert image on this forum and Hitchhiker's Visual Guide to the Qt Forum. -
Hi all, I'm a Qt beginner and met a problem when reading examples on QPaint. Here's the reimplemented paintEvent() code:
void painterTime::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); QPen pen(Qt::black); pen.setWidth(6); painter.setPen(pen); QRect r = rect().adjusted(10, 10, -10, -10); painter.drawRoundedRect(r, 20, 10); painter.save(); r.adjust(20, 20, -20, -20); painter.setViewport(r); r.moveTo(0, -r.height()/2); painter.setWindow(r); drawChart(&painter, r); painter.restore(); }
and the drawChart() member function is defined as follows:
void painterTime::drawChart(QPainter *painter, const QRect &rect) { painter->setPen(Qt::red); painter->drawLine(0, 0, rect.width(), 0); }
The resulting paint is:
Which is not what I'm expecting it to be.Since I suppose the origin of painter coordinate system to be the default origin of widget client region, namely the top-left corner of geometry(), the result should be something like this:
because in drawChart function, a line is drawn without clipping from the origin with a length of the width of the window and viewport, and in my opinion the origion of painter is the same as the device because I have not transformed it. To confirm my guess, I modified the code paint part:void painterTime::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); QPen pen(Qt::black); pen.setWidth(6); painter.setPen(pen); int w = rect().width(); int h = rect().height(); painter.setWindow(0, -h/2, w, h); painter.setViewport(w/4, h/4, w/2, h/2); painter.drawRect(0, -h/2, w, h); }
It draws as expected and confirms my guesss that painter coordinate system is the same as that of the device:
My logic is deducted as follows:
So I got a contradiction.My question is what actually is the coordinate system and origin of QPainter instance? How to explain this contradiction I got? If you have any question about my statement, please leave a comment! Any help will be greatly appreciated!
@David406
if you can confirms that the coordinate system is the same as the device from the paintEvent you modified. I think you know thatsetViewport
changes the physical coordinate toQRect(w/4,h/4,w/2,h/2)
, andsetWindow
changes the logical coordinate toQRect(0,-h/2,w,h)
.if I understand correctly about painter's window and viewport
now you draw a rect with logical coordinate
QRect(0,-h/2,w,h)
, it will map to physical coordinateQRect(w/4,h/4,w/2,h/2)
.for the first paintEvent,
setViewport
changes the physical coordinate toQRect(30,30,rect().width()-60,rect().height()-60)
andsetWindow
changes the logical coordinate toQRect(0,-(rect().height()-60)/2,rect().width()-60,rect().height()-60)
( x move 30 and y move ( rect().height() - 60 ) / 2 + 30 )you draw a line with logical coordinate
QLine(0,0,rect().width()-60,0)
which will map to physical coordinate
QLine(30,30+(rect().height()-60)/2,rect().width()-30,30+(rect().height()-60)/2)
to simplify, you draw a line with logical coordinate in the middle of the painter's window, it will map to the middle of the painter's viewport
since the viewport does not touch the widget's border, this line will not touch the widget's border
-
@Flotisable
Thanks for your detailed explanation! I found that I made a mistake with the moveTo method. I have updated my question and added a picture deducting my logic for the confirmation code. Could you please take a look at it and suggest if I'm right on the coordinates? By the way, you might need to open this picture in your desktop so as to zoom in. -
@Flotisable
Thanks for your detailed explanation! I found that I made a mistake with the moveTo method. I have updated my question and added a picture deducting my logic for the confirmation code. Could you please take a look at it and suggest if I'm right on the coordinates? By the way, you might need to open this picture in your desktop so as to zoom in.@David406
your logic about the confirmation code is the same as mine. maybe it's my bad explanation that you don't get the point.so do you understand why the result of paint does not match your expectation?
to explain more clear, I use picture to explain step by step
from the start you have a rect of the widget
after
painter.setViewport( r )
, the viewport will be
after
painter.setWindow( r )
, you will have a window
( to make the picture more clear, I do not place the window on the right place, but point out it's coordinate )
then
painter->drawLine( 0, 0, rect.width(), 0 )
will have
the line will map to viewport this way
so you get a line in the middle of the widget
this is my opinion -
@Flotisable
Thanks a lot. I get your point and it helped me realize that I made a mistake on the moveTo method. Now everything is clear. BTW, could I ask with what tool do you draw your pictures? -
@Flotisable
Thanks a lot. I get your point and it helped me realize that I made a mistake on the moveTo method. Now everything is clear. BTW, could I ask with what tool do you draw your pictures?@David406
I use "libreoffice draw"