Results 1 to 4 of 4

Thread: Adding Scale in Qt Painting

  1. #1
    Join Date
    Dec 2010
    Posts
    14
    Thanks
    1

    Default Adding Scale in Qt Painting

    Hi Folks,

    I would need some advice regarding the below problem.

    Problem Description:

    I have to create a painting widget , which loads a image , on which I can put marker with paint brush. The widget need to have mouse pointer centralized scaling with mouse scroll.

    I had two choices to implement it:

    1 ) Using QGraphicsView framework.

    2) implementing a simple paintarea by extending QWidget and displaying QImage on it using QPainter.

    The problem I am facing is by using either of the choices I can not implement all the features I need , the first method has nice features for implementing scaling with mouse scroll , but seems like QGraphicsView
    has it's own internal painter , so I can not use a new painter for the QPixmap inside QgraphicsView , as it gives run time exception that "QPainter::begin: A paint device can only be painted by one painter at a time." . Also the painting due to QGraphicsView is not permanent on the widget , i.e. if in next paint event I do not redraw all the previously marked content , the framework removes all the painting and restores the original image , i.e the marking is not permanent to the pixmap of the graphics item.

    In the second method I am not able to implement scaling properly and I could not find any opensource example doing the same.

    I would be very grateful for any advice solving my problem.

    Many thanks and regards

    Avanindra Singh

  2. #2
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Thanks
    101
    Thanked 15 Times in 15 Posts

    Default Re: Adding Scale in Qt Painting

    Using QTransform is a good way to implement translation and scaling features. The documentation that comes with it tells you everything you need to know, but here you go I will copy and paste some code snippets together (untested!) to give you a head start.

    Qt Code:
    1. ScalableWidget.h:
    2.  
    3. #include <QtGui>
    4.  
    5. class ScalableWidget: public QWidget
    6. {
    7. Q_OBJECT
    8.  
    9. double screenScale;
    10. QPointF screenOffset;
    11. QTransform screenTransform;
    12.  
    13. QPointF mouse; // current mouse location in pixel coordinates
    14. QPointF mappedMouse; // current mouse location in logical coordinates
    15. QPointF lastMouse; // last mouse location in pixel coordinates
    16. QPointF mouseDiff; // last mouse motion in pixel coordinates
    17. QPointF mappedMouseDiff; // last mouse motion in logical coordinates
    18.  
    19. public:
    20. ScalableWidget(QWidget* parent=0);
    21. ~ScalableWidget(){};
    22.  
    23. protected:
    24. void paintEvent(QPaintEvent*);
    25. void mousePressEvent(QMouseEvent *event);
    26. void mouseReleaseEvent(QMouseEvent *event);
    27. void mouseMoveEvent(QMouseEvent *event);
    28. void wheelEvent(QWheelEvent *event);
    29. void resizeEvent(QResizeEvent *event);
    30.  
    31. private:
    32. void updateMouse(QPointF mousePos);
    33. void updateScreenTransform();
    34.  
    35. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. ScalableWidget.cpp:
    2.  
    3. #include "ScalableWidget.h"
    4.  
    5. ScalableWidget::ScalableWidget(QWidget *parent)
    6. : QWidget(parent)
    7. {
    8. screenScale = 0.01; // 1 px is worth 0.01 value
    9. screenOffset = QPointF(0,0);
    10. }
    11.  
    12. void ScalableWidget::mousePressEvent(QMouseEvent *event)
    13. {
    14. mouseClick = event->posF();
    15. mouseClickTimeStamp = stopWatch.programTime();
    16. setCursor(Qt::ClosedHandCursor);
    17. }
    18.  
    19. void ScalableWidget::mouseMoveEvent(QMouseEvent *event)
    20. {
    21. updateMouse(event->posF());
    22.  
    23. if (event->buttons() & (Qt::LeftButton | Qt::RightButton))
    24. {
    25. screenOffset -= mappedMouseDiff;
    26. updateScreenTransform();
    27. }
    28.  
    29. update();
    30. }
    31.  
    32. void ScalableWidget::mouseReleaseEvent(QMouseEvent *event)
    33. {
    34. updateMouse(event->posF());
    35. unsetCursor();
    36. update();
    37. }
    38.  
    39. void ScalableWidget::wheelEvent(QWheelEvent *event)
    40. {
    41. if (event->delta() > 0)
    42. {
    43. screenScale /= 1.2;
    44. }
    45. else
    46. {
    47. screenScale *= 1.2;
    48. }
    49.  
    50. updateScreenTransform();
    51. updateMouse(QPointF(event->pos()));
    52. update();
    53. }
    54.  
    55. void ScalableWidget::resizeEvent(QResizeEvent* event)
    56. {
    57. updateScreenTransform();
    58. }
    59.  
    60.  
    61. void ScalableWidget::updateMouse(QPointF mousePos)
    62. {
    63. mouse = mousePos;
    64. mappedMouse = screenTransform.inverted().map(mouse);
    65. mouseDiff = (mouse - lastMouse);
    66. mappedMouseDiff = mouseDiff*screenScale;
    67. mappedMouseDiff.ry() = -mappedMouseDiff.y();
    68. lastMouse = mouse;
    69. }
    70.  
    71. // Updates the transformation from screen to logical coordinates.
    72. // This should be called each time when the scaling factor or the
    73. // screen translation changes.
    74. void ScalableWidget::updateScreenTransform()
    75. {
    76. screenTransform = QTransform();
    77. screenTransform.translate(width()/2, height()/2); // Place the origin in the center of the screen.
    78. screenTransform.scale(1.0/screenScale, -1.0/screenScale); // Flip it upside down and scale (zoom) it.
    79. screenTransform.translate(-screenOffset.x(), -screenOffset.y()); // Apply the offset.
    80. mappedMouse = screenTransform.inverted().map(mouse); //Calculate the logical mouse coordinates.
    81. }
    82.  
    83. void ScalableWidget::paintEvent(QPaintEvent*)
    84. {
    85. // Start the widget painter.
    86. QPainter painter(this);
    87.  
    88. // Apply the coordinate transformation from device coordinates ((0,0) is in the top left corner)
    89. // to logical coordinates, where the origin of the coordinate system is in the middle
    90. // and y grows upwards. A scaling factor converts from pixel values to logical units
    91. // (e.g. 100 px = 1 second).
    92. painter.setTransform(screenTransform);
    93.  
    94. // Draw anything you want here.
    95.  
    96. }
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Dec 2010
    Posts
    14
    Thanks
    1

    Default Re: Adding Scale in Qt Painting

    Thanks Cruz for the reply. QTransform was quite helpful for me. Though I am not through with my problem yet.

    I am facing problem while implementing scroll while scaling of the image. For implementing scroll for variable size widget , I used the method mentioned in Qt example http://doc.qt.nokia.com/4.7-snapshot...ageviewer.html , with one difference , I am trying to update the scroll area limits from the child widget ( ScalableWidget ) :

    Qt Code:
    1. void ScalableWidget::wheelEvent(QWheelEvent *event)
    2. {
    3.  
    4. float factor = qPow( 1.001 , event->delta() );
    5.  
    6. // screenScale *= factor;
    7.  
    8.  
    9.  
    10. if (event->delta() > 0)
    11. {
    12. screenScale /= 1.2;
    13.  
    14. factor = 1.0 / 1.2;
    15. }
    16. else
    17. {
    18. screenScale *= 1.2;
    19.  
    20. factor = 1.2;
    21. }
    22.  
    23. updateMouse(QPointF(event->pos()));
    24.  
    25. updateScreenTransform();
    26.  
    27. update();
    28.  
    29. ImageScrollArea *scrollArea = ( ImageScrollArea* )this->parent();
    30.  
    31. QScrollBar *horizontalScrollBar = scrollArea->horizontalScrollBar();
    32. QScrollBar *verticalScrollBar = scrollArea->verticalScrollBar();
    33.  
    34.  
    35. adjustScrollBar( horizontalScrollBar , factor );
    36. adjustScrollBar( verticalScrollBar , factor );
    37.  
    38. scrollArea->update();
    39.  
    40. }
    41.  
    42.  
    43. void ScalableWidget::adjustScrollBar(QScrollBar *scrollBar, double factor)
    44. {
    45.  
    46. int value = int(factor * scrollBar->value()
    47. + ((factor - 1) * scrollBar->pageStep()/2));
    48.  
    49. std::cout<<scrollBar->value()<<" "<<value<<" "<<scrollBar->pageStep()<<" -- ";
    50.  
    51. scrollBar->setValue( value );
    52.  
    53.  
    54. std::cout<<scrollBar->value()<<" "<<value<<" "<<scrollBar->pageStep()<<std::endl;
    55. }
    To copy to clipboard, switch view to plain text mode 


    The strange thing is scrollBar->setValue( value ) is not updating the new value , instead it keeps the old value. Is this beacuse of I am trying to update it from child widget?... Is this standard Qt widget property that I can not change its attribute values from inside child widgets?...


    Thanks a lot for the help.

    Avanindra Singh

  4. #4
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Thanks
    101
    Thanked 15 Times in 15 Posts

    Default Re: Adding Scale in Qt Painting

    Hello!

    setValue() should work. Did you call setWidget() to set the ScalableWidget into the scroll area? Oh and just because you change the QTransform of the painter it doesn't mean that the size of the widget changes and as far as I know the scroll bars are laid out according to the size of the contained widget. Also, try to set the scrollbar values hard to 0 or a large number to check if they do anything at all and see if the problem is in that part or maybe in the calculation of the factor.

Similar Threads

  1. QDial disabling key scroll and mouse wheel scroll
    By ldg20 in forum Qt Programming
    Replies: 2
    Last Post: 2nd June 2010, 23:05
  2. adding items in scroll area dynamically
    By Ezhil in forum Qt Programming
    Replies: 5
    Last Post: 22nd May 2009, 16:33
  3. Adding scroll bars to a main window
    By dougab in forum Newbie
    Replies: 9
    Last Post: 25th December 2007, 20:27
  4. Replies: 6
    Last Post: 14th April 2006, 05:39
  5. QRubberBand painting in the scroll area widget
    By SkripT in forum Qt Programming
    Replies: 7
    Last Post: 17th January 2006, 16:48

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
  •  
Qt is a trademark of The Qt Company.