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:
    alternate text
    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:
    alternate text
    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:
    alternate text
    My logic is deducted as follows:
    alt text
    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!


  • Moderators

    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: ![alternate text](image-url).See also How to insert image on this forum and Hitchhiker's Visual Guide to the Qt Forum.



  • @David406
    if you can confirms that the coordinate system is the same as the device from the paintEvent you modified. I think you know that setViewport changes the physical coordinate to QRect(w/4,h/4,w/2,h/2), and setWindow changes the logical coordinate to QRect(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 coordinate QRect(w/4,h/4,w/2,h/2).

    for the first paintEvent, setViewport changes the physical coordinate to QRect(30,30,rect().width()-60,rect().height()-60)
    and setWindow changes the logical coordinate to QRect(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

    sample



  • @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
    rect

    after painter.setViewport( r ), the viewport will be
    rect and view port

    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 )
    rect, viewport and window

    then painter->drawLine( 0, 0, rect.width(), 0 ) will have
    rect, viewport and window with a line

    the line will map to viewport this way
    rect, viewport and window with a line map to viewport

    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?



  • @David406
    I use "libreoffice draw"


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.