Results 1 to 12 of 12

Thread: QPainter, scale(), and setFont()

  1. #1
    Join Date
    Oct 2007
    Posts
    17
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default QPainter, scale(), and setFont()

    Hello everyone,

    I'm having some trouble with QPainter and scaling. My goal is to implement a simple graphing tool, so I subclassed QWidget and paintEvent(). I want to draw a 20x20 traditional coordinate plane, with (0,0) in the center. So far, I've been able to do so with translate(width()/2, height()/2) and scale(-width()/20, -height()/20), but when I try to use drawFont(), the text is huge and upside down. I would like to have drawFont(QPoint(...), ...) to draw text on logical coordinates. Should I use a separate QPainter...??
    Browsing the forums, I have also tried inverting the matrix before drawing text, but it didn't work. I'm pretty lost here. Does anyone have any ideas? Thanks!

  2. #2
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    Translating the coordinate system should be enough. Why do you scale it? This actually results in a mirrored and scaled coordinate system.

  3. #3
    Join Date
    Oct 2007
    Posts
    17
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    Thanks, it should be:

    Qt Code:
    1. painter.scale(width()/20, height()/20);
    To copy to clipboard, switch view to plain text mode 

    Because when I draw a line specifying the coordinates (0,-10) to (0,10), for example, I want it to extend the whole height of the widget (for drawing the y axis).

    However, I still have the big text problem when I try to label the tickmarks on the axises. Here's a screenshot: http://www.screencast.com/t/9y2mocrO

    Thank you for your help.
    Last edited by c_07; 15th December 2007 at 01:44.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    Try this:
    Qt Code:
    1. void paintEvent( QPaintEvent * )
    2. {
    3. QPainter p( this );
    4.  
    5. p.save();
    6.  
    7. // set up "traditional" coordinate system
    8. p.setWindow( -10, -10, 20, 20 );
    9. p.scale( 1.0, -1.0 );
    10. QTransform t = p.combinedTransform();
    11.  
    12. // draw the graph
    13. p.drawLine( 0, 0, 5, 5 );
    14.  
    15. // revert to the default coordinate system
    16. p.restore();
    17.  
    18. // draw labels in the Right Place(tm) using t transform
    19. QPoint pt( 7, 7 );
    20. p.drawText( t.map( pt ), "xxx" );
    21. }
    To copy to clipboard, switch view to plain text mode 
    Instead of using save()/restore() you can prepare the right QTransform yourself and map all points.

    Another solution is to scale the font, but it might not work with all fonts. Also take a look at Qwt.

  5. The following user says thank you to jacek for this useful post:

    c_07 (16th December 2007)

  6. #5
    Join Date
    Oct 2007
    Posts
    17
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    Thank you Jacek... you made sense of a complicated subject (I think) very quickly
    I set the anti-aliasing mode to true and it looked even better.
    I would use Qwt except that I am trying to learn the in's and out's of QPainter, and also because I am just trying to develop a very simple application to demonstrate L'Hospital's rule for fun (and extra credit) in my Calculus class.

  7. #6
    Join Date
    Oct 2007
    Posts
    17
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    And now...

    I subclassed mouseEvent() to detect clicks inside the widget, because based on where the mouse click's position, I want to re-center the graph to that point. In the subclass function I passed event->pos() to my painting widget, but I need to transform the physical coordinates from the mouse click into logical coordinates that I can use. I tried map() and that didn't seem to work...?

  8. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    event->pos() returns position in widget coordinates, but that t transform maps plot coordinates to widget coordinates, so you need the opposite transformation ("QTransform invT = t.inverted()").

  9. The following user says thank you to jacek for this useful post:

    c_07 (16th December 2007)

  10. #8
    Join Date
    Oct 2007
    Posts
    17
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    Thank you again, Jacek, that worked nicely.

  11. #9
    Join Date
    Oct 2007
    Posts
    17
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    Well, I'm almost there, but I'm scratching my head over this one...

    I've noticed that when I double click on the center (0,0) when I've zoomed out a ways, it re-orients to (1,-2) instead of staying where it should. In fact, at a 20x20 rectangle, the coordinates are always off by that much, but the error margin decreases slightly as the zoom increases. In fact, when I zoom in to about a 4x4 rectangle, the re-centering works perfectly. Next moving to a 6x6 view rect., the x value returned for the dbl-click event is correct, but the y value is off by one. The error margin keeps increasing as the viewing rect is increased (I zoom out on the graph).

    Here's the code for the slot that handles the double-click-on-graph event:
    Qt Code:
    1. void PainterWidget::centerChanged(QPoint center) {
    2. QTransform pInvertTransform = pTransform.inverted();
    3. QPoint mapped_center = pInvertTransform.map(center);
    4. currentCenter = mapped_center;
    5.  
    6. int newx = mapped_center.x()+(-rectOriginalFunction.width()/2);
    7. int newy = -mapped_center.y()+(-rectOriginalFunction.height()/2);
    8.  
    9. //Don't change the dimensions of the graph
    10. int samew = rectOriginalFunction.width();
    11. int sameh = rectOriginalFunction.height();
    12.  
    13. //Clicking on the origin of a 20x20 graph [Rect(-10,-10,20,20)] results in
    14. // the rect (-9,-12,20,20) and a center at (1,-2)
    15. // etc.
    16. setOriginalFunctionRect(QRect(newx,newy,samew,sameh));
    17. }
    To copy to clipboard, switch view to plain text mode 

    Any ideas? Thanks!
    Last edited by c_07; 29th December 2007 at 00:00.

  12. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    It might be caused by some rounding errors, since you perform all calculations on integers. Another possibility is that the "active" point of the cursor is in a bit different place than you would expect.

  13. #11
    Join Date
    Oct 2007
    Posts
    17
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    If rounding errors were indeed the case, then (and that seems to make sense), how could I best circumvent the problem? I can use floats instead of integers, but I can only use QPainter::setWindow() with a QRect, not a QRectF, and this seems to be the underlying hindrance since I set the QTransform with a call to QPainter::combinedTransform() shortly thereafter.

  14. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QPainter, scale(), and setFont()

    Quote Originally Posted by c_07 View Post
    but I can only use QPainter::setWindow() with a QRect, not a QRectF
    Yes, but you can avoid some of the errors by changing QRectF to QRect in the last step before the call to setWindow().

    QTransform uses floats internally, so first I would check whether mapped_center has correct coordinates and whether changing it to QPointF helps.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.