0

To make it simple, my application has two scroll bars. when any scroll bar changes, the QPainter re-paints images.

code pieces:

  // connect valueChanged to update
  connect(this->horizontalScrollBar(),
      SIGNAL(valueChanged(int)),
      this,
      SLOT(UpdateVisibleArea()));

  connect(this->verticalScrollBar(),
      SIGNAL(valueChanged(int)),
      this,
      SLOT(UpdateVisibleArea()));

in UpdateVisibleArea(), the QWidget.update() method is called. and the QWidget.paintEvent() method is implemented like the following:

QPixmap q_pixmap;
if (!ImageCache::GetPixmap(cache_key, &q_pixmap)) {
    // there're up to thousands of images, we can not pre-load them all into the cache.
    // the following statement may take 80~250ms.
    loadImage(cache_key, &q_pixmap);    
    ImageCache::PutPixmap(cache_key, q_pixmap);
}

QPainter q_painter;
q_painter.drawPixmap(...);  // usually it takes less than 20ms.

The problem:

when I drag scroll bars quickly, it feels pretty laggy.

My thoughts:

  1. The images should be loaded in background thread. but the problem is, the qpainter instance is waiting on the UI thread. it can not proceed when the image is not ready.
  2. Is there any way to prevent repainting happening so fast when scroll bar changes quickly?

My question:

Can you please give me some clue on how to optimize it?

Wang Xiaoming
  • 19
  • 1
  • 5
  • Maybe too many updates and the background is also drawn. Your code example is too small to make an opinion. I would also try offscreen rendering if comes to producing one picture out of many elements: https://www.google.com/search?q=qt+offscreen+rendering+example – Alexander V Nov 05 '17 at 04:30
  • @AlexanderVX it doesn't take long to paint (<20ms). so it might not be the bottleneck. – Wang Xiaoming Nov 05 '17 at 04:40
  • Composing many drawings in one also prevent flicker. – Alexander V Nov 05 '17 at 05:03
  • It's possible to disable scrolbars if your paint device is a QGraphicsVeiw, but for optimizations you should describe more on your scenario and why you are always repaint continuously is that show some thing like animations. – saeed Nov 05 '17 at 05:39
  • If "laggy" means it flickers, do offscreen rendering like @AlexanderVX propose. It is the right way of doing software painting without flickering since win95 – Xplatforms Nov 06 '17 at 06:57
  • thanks guys. I'll consider doing off-screen rendering. @AlexanderVX, could you please make your comment an answer? so I can accept it. – Wang Xiaoming Nov 06 '17 at 14:34

1 Answers1

0

How can I optimize the complex drawing for many objects in scrolled content?

That can be done with "offscreen rendering" when we populate the graphics buffer before it is actually drawn on the screen. In case of scrolling we can either prepopulate the whole scroll content as one big rectangular area or we can use large enough rectangular "window" so that we scroll easier. Should we use smaller scroll window buffer and not the whole scroll rectangle for the offscreen rendering depends on the size of the scrolled content.

Using OpenGL and framebuffer can improve this technique even further. That can be done either with QOpenGLWidget or using QML QQuickPaintedItem (that implies entire UI is QML, though). The second example is not elaborated for the offscreen buffer technique, though, but just shows the use of framebuffer in QML. That same technique from the first example can be applied there with a bit of change.

Alexander V
  • 8,351
  • 4
  • 38
  • 47