需要有关Qt绘画的性能改进建议



为了简单起见,我的应用程序有两个滚动条。 当任何滚动条更改时,QPainter 会重新绘制图像。

代码片段

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

在 UpdateVisibleArea() 中,调用了 QWidget.update() 方法,QWidget.paintEvent() 方法的实现方式如下:

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.

问题:

当我快速拖动滚动条时,感觉很滞后。

我的想法

  1. 图像应在后台线程中加载。 但问题是,QPainter 实例正在等待 UI 线程。 当图像未准备好时,它无法继续。
  2. 当滚动条快速变化时,有没有办法防止重新绘制发生得如此之快?

我的问题

你能给我一些关于如何优化它的线索吗?

如何优化滚动中许多对象的复杂绘图 内容?

这可以通过"屏幕外渲染"来完成,当我们在屏幕上实际绘制图形缓冲区之前填充图形缓冲区时。在滚动的情况下,我们可以将整个滚动内容预填充为一个大的矩形区域,或者我们可以使用足够大的矩形"窗口",以便我们更容易滚动。我们是否应该使用较小的滚动窗口缓冲区,而不是整个滚动矩形进行屏幕外渲染,这取决于滚动内容的大小。

使用 OpenGL 和帧缓冲可以进一步改进这种技术。这可以通过QOpenGLWidget或使用QML QQuickPaintedItem来完成(这意味着整个UI都是QML)。不过,第二个示例并未针对屏幕外缓冲区技术进行详细说明,而只是展示了在 QML 中使用帧缓冲区。第一个示例中的相同技术可以在那里应用,只需稍作更改。

最新更新