Results 1 to 5 of 5

Thread: Performance problem with drawing circles

  1. #1
    Join Date
    Jun 2007
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Performance problem with drawing circles

    It is possible to drag with pressed right mouse button and to zoom with mouse wheel. And initially everything works rather smooth. But when I zoom to the smallest circle the performance of drawing is significantly degraded. Why? And how can I fix it?

    Qt Code:
    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3.  
    4. #include <QWidget>
    5. #include <QList>
    6.  
    7. struct circle {
    8. qreal r;
    9. circle(QPointF center, qreal radius): c(center), r(radius) {}
    10. };
    11.  
    12. class Widget : public QWidget
    13. {
    14. Q_OBJECT
    15.  
    16. public:
    17. Widget(QWidget *parent = 0);
    18.  
    19. protected:
    20. void paintEvent(QPaintEvent *event);
    21.  
    22. void mousePressEvent(QMouseEvent *event);
    23. void mouseReleaseEvent(QMouseEvent *event);
    24. void mouseMoveEvent(QMouseEvent *event);
    25.  
    26. void wheelEvent(QWheelEvent *event);
    27.  
    28. private:
    29. QList<circle> circles;
    30. QPointF shift;
    31. qreal scale;
    32. QPoint previous;
    33. bool isDragging;
    34. };
    35.  
    36. #endif // WIDGET_H
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include "widget.h"
    2.  
    3. #include <math.h>
    4. #include <QPainter>
    5. #include <QMouseEvent>
    6. #include <QWheelEvent>
    7.  
    8. circle tangent2(const circle &c1, const circle &c2, qreal r, const QPointF &p)
    9. {
    10. qreal r1 = c1.r + r;
    11. qreal r2 = c2.r + r;
    12. qreal d = c1.r + c2.r;
    13. qreal dx = (d*d - r2*r2 + r1*r1)/(2*d);
    14. qreal dy = sqrt(r1*r1 - dx*dx);
    15. QPointF v = (c2.c - c1.c)/d;
    16. QPointF n(-v.y(), v.x());
    17. QPointF pv = p - c1.c;
    18. if (pv.x()*n.x() + pv.y()*n.y() < 0)
    19. n = -n;
    20. QPointF c = c1.c + dx*v + dy*n;
    21. return circle(c, r);
    22. }
    23.  
    24. circle tangent3(const circle &c1, const circle &c2, const circle &c3)
    25. {
    26. qreal k1 = 1/c1.r;
    27. qreal k2 = 1/c2.r;
    28. qreal k3 = 1/c3.r;
    29. qreal a = k1 + k2 + k3;
    30. qreal b = 2*sqrt(k1*k2 + k2*k3 + k3*k1);
    31. qreal k = qMax(qAbs(a - b), a + b);
    32. return tangent2(c1, c2, 1/k, c3.c);
    33. }
    34.  
    35. Widget::Widget(QWidget *parent)
    36. : QWidget(parent), shift(300, 400), scale(30), isDragging(false)
    37. {
    38. setAutoFillBackground(false);
    39. circle c1(QPointF(0, 0), 5);
    40. circle c2(QPointF(8, 0), 3);
    41. circle c3 = tangent2(c1, c2, 4, QPointF(0, -1));
    42. circles << c1 << c2 << c3;
    43. for (int i = 0; i < 6; ++i) {
    44. circle c = tangent3(c1, c2, c3);
    45. circles << c;
    46. c1 = c2;
    47. c2 = c3;
    48. c3 = c;
    49. }
    50. }
    51.  
    52. void Widget::paintEvent(QPaintEvent *event)
    53. {
    54. QPainter painter(this);
    55. painter.fillRect(0, 0, width(), height(), Qt::darkGray);
    56. painter.setBrush(Qt::NoBrush);
    57. painter.setPen(QPen(QBrush(Qt::white), 1.5));
    58. painter.setRenderHint(QPainter::Antialiasing, true);
    59. foreach(const circle &c, circles)
    60. painter.drawEllipse(c.c * scale + shift, c.r * scale, c.r * scale);
    61. }
    62.  
    63. void Widget::mousePressEvent(QMouseEvent *event)
    64. {
    65. if (!isDragging && event->button() == Qt::RightButton) {
    66. isDragging = true;
    67. previous = event->pos();
    68. }
    69. }
    70.  
    71. void Widget::mouseReleaseEvent(QMouseEvent *event)
    72. {
    73. if (isDragging && event->button() == Qt::RightButton) {
    74. isDragging = false;
    75. }
    76. }
    77.  
    78. void Widget::mouseMoveEvent(QMouseEvent *event)
    79. {
    80. if (isDragging) {
    81. shift += event->pos() - previous;
    82. previous = event->pos();
    83. repaint();
    84. }
    85. }
    86.  
    87. void Widget::wheelEvent(QWheelEvent *event)
    88. {
    89. int numDegrees = event->delta() / 8;
    90. int numTicks = numDegrees / 15;
    91. qreal factor = pow(1.2, -numTicks);
    92. shift += (1 - factor) * (event->pos() - shift);
    93. scale *= factor;
    94. repaint();
    95. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include <QtGui/QApplication>
    2. #include "widget.h"
    3.  
    4. int main(int argc, char *argv[])
    5. {
    6. QApplication a(argc, argv);
    7. Widget w;
    8. w.resize(800, 600);
    9. w.show();
    10. return a.exec();
    11. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2007
    Location
    Paris
    Posts
    459
    Thanks
    98
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4 Qt5

    Default Re: Performance problem with drawing circles

    If you want a fast an advanced canvas with zoom:

    Use QGraphicsView.

  3. #3
    Join Date
    Jun 2007
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Performance problem with drawing circles

    Quote Originally Posted by bunjee View Post
    If you want a fast an advanced canvas with zoom:

    Use QGraphicsView.
    This is not possible for me because there is a limitation:
    QGraphicsItem does not support use of cosmetic pens with a non-zero width.
    And I need to draw my shapes with pen width that is the same for all zoom levels. So painting bounds for shapes are different for different zoom levels and QGraphicsView can't handle such cases, am I right?

    In any case I'll try to reproduce this behaviour with QGraphicsView, cause I think the problem is somewhere in QPainter.

  4. #4
    Join Date
    Jun 2007
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Performance problem with drawing circles

    By the way here is a Java2D implementation (just rename the attachment to jar) and there is no such problem with performance as in Qt. So what is wrong with my approach to zooming in Qt version?
    Attached Files Attached Files

  5. #5
    Join Date
    Jun 2007
    Posts
    23
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Performance problem with drawing circles

    I have run this simple example with callgring profiler and here are the results.

    When zoom level is not big and everything is rather fast:


    With big zoom level and degraded performance:


    So the problem begins with the call of function QPainter::intersected.
    What is wrong in my example? Is this a known Qt4 limitation/feature or bug?

Similar Threads

  1. Replies: 4
    Last Post: 7th May 2008, 00:01
  2. graphicsview performance problem
    By kernel_panic in forum Qt Programming
    Replies: 16
    Last Post: 23rd December 2007, 18:19
  3. QTableView Performance Problem on Windows
    By umitoz in forum Qt Programming
    Replies: 1
    Last Post: 31st August 2007, 16:47
  4. QPainterPath drawing problem
    By shad in forum Qt Programming
    Replies: 3
    Last Post: 17th January 2007, 13:30
  5. drawing problem
    By boss_bhat in forum Newbie
    Replies: 1
    Last Post: 20th September 2006, 10:49

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.