Results 1 to 20 of 22

Thread: Drawing lines in QPainter takes a lot of time

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Mar 2016
    Posts
    14
    Thanks
    1
    Thanked 2 Times in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Drawing lines in QPainter takes a lot of time

    Hi,

    I currently have a problem with line drawing in QPainter. I draw "only" simple 2000 lines but it takes something like 50ms for each update. My problem is all the lines continuously move to draw a nice slowly rotating graph (note : it's not just a rotate()).
    To check I run the following code only :
    Qt Code:
    1. void Widget::paintEvent(QPaintEvent *event)
    2. {
    3. QElapsedTimer chronoPainter;
    4.  
    5. QPainter myPainter(this);
    6. const int cst_nbLines = 5000;
    7.  
    8. chronoPainter.start();
    9. for (int i=0 ; i<cst_nbLines ; i++)
    10. {
    11. QLine myLine(i/10, i/10, i/10+300, i/10);
    12. myPainter.drawLine(myLine);
    13. }
    14. qint64 elapsed_ns = chronoPainter.nsecsElapsed();
    15. qint64 elapsed_ms = elapsed_ns/1000000L;
    16.  
    17. qDebug() << "End, time to paint : " << elapsed_ms << "ms";
    18. }
    To copy to clipboard, switch view to plain text mode 

    And drawing my 2000 very simple lines takes... 50ms. Not way to have a 50FPS animation with that. Have you got an idea of how I can draw all the lines faster?
    I've tried with
    Qt Code:
    1. QVector<QLine> linesVector;
    2. for (int i=0 ; i<cst_nbLines ; i++)
    3. {
    4. linesVector.append(QLine(i/10, i/10, i/10+300, i/10));
    5. }
    6. myPainter.drawLines(linesVector);
    To copy to clipboard, switch view to plain text mode 
    but it not helps (same drawing time).

    Thank you!
    Last edited by xcxl; 4th June 2019 at 13:55.

  2. #2
    Join Date
    Mar 2008
    Location
    Kraków, Poland
    Posts
    1,536
    Thanked 284 Times in 279 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    Did you know that in your example, you draw every line 10 times?

  3. #3
    Join Date
    Mar 2016
    Posts
    14
    Thanks
    1
    Thanked 2 Times in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    Quote Originally Posted by Lesiok View Post
    Did you know that in your example, you draw every line 10 times?
    Hummm no I didn't know... I just add a counter (counter+=1 just after the drawLine()), and I really have 5000 iterations. Could you explain why you said I draw it 10 times please?

  4. #4
    Join Date
    Mar 2008
    Location
    Kraków, Poland
    Posts
    1,536
    Thanked 284 Times in 279 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    Because i is integer for i in <0,9> i/10 == 0.

  5. #5
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    Quote Originally Posted by xcxl View Post
    Qt Code:
    1. QVector<QLine> linesVector;
    2. for (int i=0 ; i<cst_nbLines ; i++)
    3. {
    4. linesVector.append(QLine(i/10, i/10, i/10+300, i/10));
    5. }
    6. myPainter.drawLines(linesVector);
    To copy to clipboard, switch view to plain text mode 
    Likely not directly responsible, but call QVector::reserve() before that loop.
    Otherwise you could get 5000 memory realliocations.

    Cheers.
    _

  6. #6
    Join Date
    Jan 2006
    Location
    Bremen, Germany
    Posts
    554
    Thanked 86 Times in 81 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    Quote Originally Posted by anda_skoa View Post
    Otherwise you could get 5000 memory realliocations.
    Not 5000 but also not only 1.

  7. #7
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    If you do not need to change the graphics with every paint event, then use a QPainterPath as a member variable of the Widget class. During the paintEvent(), all you need to do is call QPainter::drawPath(). When the graphics need to be changed, re-create the content of the QPainterPath and then call QWidget::update() if needed. For even faster performance, draw to an offscreen QImage and use QPainter::drawImage() in the paint event.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  8. #8
    Join Date
    Mar 2016
    Posts
    14
    Thanks
    1
    Thanked 2 Times in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    Hi everybody, thanks for the answers!

    Quote Originally Posted by Lesiok
    Because i is integer for i in <0,9> i/10 == 0.
    Sorry, I didn't understand your sentence. You said I draw every lines 10 times with the same coordinates, and I understood "the loop run 10x cst_nbLines".

    Quote Originally Posted by d_stranz View Post
    If you do not need to change the graphics with every paint event, then use a QPainterPath as a member variable of the Widget class. During the paintEvent(), all you need to do is call QPainter::drawPath(). When the graphics need to be changed, re-create the content of the QPainterPath and then call QWidget::update() if needed. For even faster performance, draw to an offscreen QImage and use QPainter::drawImage() in the paint event.
    I tried each methods (code below for any other visitors), the results are (for 5000 lines) :

    - With all myPainter.drawLine(myLine) => 17ms
    - With myPainter.drawLines(linesVector) and a reserve() => 17ms
    - With myPainter.drawPath() => 17 ms, it looks like this fct draw every lines as before...
    - With myPainter.drawImage() => <1ms for drawing the pixmap. Very fast but if a do an animation with a move of each points at each frame, it takes between 30-40ms to generate the QImage

    So nothing under 17ms to draw my 5000 moving lines. I don't know why it takes so long, drawing 5000 simple points takes 1-2ms. Would it be faster to draw with OpenGL directly? 5k lines is nothing compared with complex 3D models...

    The code :
    Qt Code:
    1. const int cst_nbLines = 5000;
    2.  
    3. // TEST1
    4. for (int i=0 ; i<cst_nbLines ; i++)
    5. {
    6. QLine myLine(i/10, i/10, i/10+300, i/10);
    7. myPainter.drawLine(myLine);
    8.  
    9. }
    10.  
    11. // TEST2
    12. QVector<QLineF> linesVector;
    13. linesVector.reserve(cst_nbLines);
    14. for (int i=0 ; i<cst_nbLines ; i++)
    15. {
    16. //linesVector.append(QLine(i/10, i/10, i/10+300, i/10));
    17. linesVector.append(QLineF(i/10, i/10, i/10+300, i/10));
    18. counter++;
    19. }
    20. myPainter.drawLines(linesVector);
    21.  
    22. // TEST3
    23. myPainter.drawPath(myPath);
    24.  
    25. // TEST4
    26. generateQImage();
    27. myPainter.drawImage(QPoint(0,0), *myImage);
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    The code :
    Where does this code live? In the paintEvent()? The creation of the QPainterPath and QImage for tests 3 and 4 should occur outside the paintEvent.

    OpenGL would probably be faster, but you probably know that in modern OpenGL you don't do any active drawing - you create the equivalent of a scene that the rendering pipeline and shaders process to put on screen. So your programming model will be similar to that used in the Qt Graphics / View architecture.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  10. #10
    Join Date
    Mar 2008
    Location
    Kraków, Poland
    Posts
    1,536
    Thanked 284 Times in 279 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    Maybe I repeat myself but... This is the original code :
    Qt Code:
    1. const int cst_nbLines = 5000;
    2.  
    3. for (int i=0 ; i<cst_nbLines ; i++)
    4. {
    5. QLine myLine(i/10, i/10, i/10+300, i/10);
    6. myPainter.drawLine(myLine);
    7. }
    To copy to clipboard, switch view to plain text mode 
    This is the code giving the same final result but 10 times faster :
    Qt Code:
    1. const int cst_nbLines = 5000;
    2.  
    3. for (int i=0 ; i<cst_nbLines/10 ; i++)
    4. {
    5. QLine myLine(i, i, i+300, i);
    6. myPainter.drawLine(myLine);
    7. }
    To copy to clipboard, switch view to plain text mode 

  11. #11
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    This is the code giving the same final result but 10 times faster :
    I think the OP understands he is drawing the same line 10 times. He misunderstood your original comment (as I did when I first read it) to say that he was executing the loop 10 times (to give 50k lines). His point is that even if these were 5000 individual lines with different coordinates, the time it takes to draw all of them is too long, no matter what method he uses.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  12. #12
    Join Date
    Mar 2016
    Posts
    14
    Thanks
    1
    Thanked 2 Times in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    Quote Originally Posted by d_stranz View Post
    Where does this code live? In the paintEvent()? The creation of the QPainterPath and QImage for tests 3 and 4 should occur outside the paintEvent.

    OpenGL would probably be faster, but you probably know that in modern OpenGL you don't do any active drawing - you create the equivalent of a scene that the rendering pipeline and shaders process to put on screen. So your programming model will be similar to that used in the Qt Graphics / View architecture.
    Yes this code is in the paintEvent (only one test at a time of course), and the creation of the QPainterPath and QImage is in the QWidget constructor. I understand the problem with OpenGL. It is just that drawing 5000 lines doesn't look a lot to me, but it may be normal for it to take 10-20ms. I thought I was doing something wrong. Maybe the best way for me to draw very fast is to modify each pixel one by one by myself on a QPixmap.

    Quote Originally Posted by Lesiok
    This is the code giving the same final result but 10 times faster
    Yes I understand Lesiok but the goal of this example is to draw 5000 lines, in a full window (to avoid partial drawing) without scaling anything to be sure to have default parameters.
    Of course the code could be :

    Qt Code:
    1. for (int i=0 ; i<cst_nbLines ; i++)
    2. {
    3. linesVector.append(QLineF(double(i)/10.0, double(i)/10.0, double(i)/10.0+100.0, double(i)/10.0));
    4. }
    To copy to clipboard, switch view to plain text mode 
    It gives me the same time to draw, but looks less clear to me for a basic example.

  13. #13
    Join Date
    Mar 2008
    Location
    Kraków, Poland
    Posts
    1,536
    Thanked 284 Times in 279 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    OK, it's clear.

  14. #14
    Join Date
    Mar 2016
    Posts
    14
    Thanks
    1
    Thanked 2 Times in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    For later visitors, I found on internet some algorithms probably faster to draw all my lines pixels by pixels on a QImage.
    I will try the Bresenham's line algorithm and see.

  15. #15
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    I am pretty sure that is what the Qt Raster backend is using or an even more advanced algorithm.

    And the raster backend uses lots of CPU extension (e.g. SSE5) were possible.

    Cheers,
    _

  16. #16
    Join Date
    Mar 2016
    Posts
    14
    Thanks
    1
    Thanked 2 Times in 1 Post
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Drawing lines in QPainter takes a lot of time

    Quote Originally Posted by anda_skoa View Post
    I am pretty sure that is what the Qt Raster backend is using or an even more advanced algorithm.

    And the raster backend uses lots of CPU extension (e.g. SSE5) were possible.

    Cheers,
    _
    Hi anda_skoa, just for "fun" I tried to implement my own fast line drawing algorithm, with the hope that I can do better knowing at the start the size of line, color, etc.
    But you were right, I draw everything in 40ms instead of 50ms, which is a bit better but not really different. I think I will just keep the Qt code for drawing all the lines and do with a "low FPS".

    I let my code here for future visitors :
    Qt Code:
    1. void RenderGraphThread::testFctFastLineDrawingAlgorithm(QImage &r_image, int32_t x1, int32_t y1, int32_t x2, int32_t y2)
    2. {
    3. int x,y,dx,dy,dx1,dy1,px,py,xe,ye,i;
    4. dx=x2-x1;
    5. dy=y2-y1;
    6. dx1=std::abs(dx);
    7. dy1=std::abs(dy);
    8. px=2*dy1-dx1;
    9. py=2*dx1-dy1;
    10. if(dy1<=dx1)
    11. {
    12. if(dx>=0)
    13. {
    14. x=x1;
    15. y=y1;
    16. xe=x2;
    17. }
    18. else
    19. {
    20. x=x2;
    21. y=y2;
    22. xe=x1;
    23. }
    24. testFctPutPixelOnImage(r_image,x,y, 0xFF0B9F8A); // green
    25. for(i=0;x<xe;i++)
    26. {
    27. x=x+1;
    28. if(px<0)
    29. {
    30. px=px+2*dy1;
    31. }
    32. else
    33. {
    34. if((dx<0 && dy<0) || (dx>0 && dy>0))
    35. {
    36. y=y+1;
    37. }
    38. else
    39. {
    40. y=y-1;
    41. }
    42. px=px+2*(dy1-dx1);
    43. }
    44. testFctPutPixelOnImage(r_image,x,y, 0xFF0B9F8A); // green
    45. }
    46. }
    47. else
    48. {
    49. if(dy>=0)
    50. {
    51. x=x1;
    52. y=y1;
    53. ye=y2;
    54. }
    55. else
    56. {
    57. x=x2;
    58. y=y2;
    59. ye=y1;
    60. }
    61. testFctPutPixelOnImage(r_image,x,y, 0xFF0B9F8A); // green
    62. for(i=0;y<ye;i++)
    63. {
    64. y=y+1;
    65. if(py<=0)
    66. {
    67. py=py+2*dx1;
    68. }
    69. else
    70. {
    71. if ((dx<0 && dy<0) || (dx>0 && dy>0))
    72. {
    73. x=x+1;
    74. }
    75. else
    76. {
    77. x=x-1;
    78. }
    79. py=py+2*(dx1-dy1);
    80. }
    81. testFctPutPixelOnImage(r_image,x,y, 0xFF0B9F8A); // green
    82. }
    83. }
    84. }
    85.  
    86. // TEST CODE FOR FAST DRAWING LINES
    87. void RenderGraphThread::testFctPutPixelOnImage(QImage &r_image, const int32_t x, const int32_t y, const uint32_t _color)
    88. {
    89. if (y<r_image.height() && x<r_image.width() && x>=0 && y>=0)
    90. {
    91. uchar *pFirstLine = r_image.bits();
    92. int32_t depth = 4;
    93. QRgb* rgbpixel = reinterpret_cast<QRgb*>(pFirstLine + r_image.width()*depth*y + x*depth);
    94. *rgbpixel = _color;
    95. }
    96. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. Drawing Lines In Real Time (PyQt)
    By n3ziy in forum Qt Programming
    Replies: 1
    Last Post: 24th April 2016, 20:09
  2. drawing lines on a canvas and move them dynamically
    By smrati.johri in forum Newbie
    Replies: 4
    Last Post: 7th April 2016, 23:35
  3. Drawing lines on qwtpolarplot
    By jerrychan in forum Qwt
    Replies: 3
    Last Post: 12th June 2013, 11:55
  4. drawing lines using qpainter from file
    By neutrino in forum Qt Programming
    Replies: 2
    Last Post: 9th February 2013, 10:03
  5. Drawing row/column lines in QTreeWidget
    By warvimo in forum Newbie
    Replies: 0
    Last Post: 25th May 2012, 18:33

Tags for this Thread

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.