Qt:QGraphicsView中慢速垂直滚动的解决方法,包含许多项目

时间:2015-10-09 20:33:18

标签: c++ performance qt qgraphicsview

编辑我发现了一个非常简单的解决方法,请参阅帖子的结尾。尽管如此,我仍然愿意接受评论和建议,因为我的“修复”显然不是事情的意图......

我的Qt / PyQt应用程序有一个带有大型场景的QGraphicsView,其中有许多项目是垂直堆叠的。 Verical Scrolling和其他鼠标交互非常慢,但仅限于场景的上半部分,滚动到下半部分后,鼠标交互突然变得活泼。这种行为让我觉得一些BSTree持有这些项目一定存在问题,但我不熟悉Qt内部。我为Qt 4.7找到了一个旧的Bug报告(QTBUG-11059),正好描述了我的问题,但它没有任何修复就关闭了。我能够在Qt 5.4&amp ;;中重现这一点。 5.5,确认这是一个Qt问题,而不是Python / PyQt的性能问题。

我不确定此问题的最佳修复/解决方法是什么:

  • 我错过了一些隐藏的优化标记/设置会产生更好的性能吗?我尝试了setItemIndexMethod(QGraphicsScene.NoIndex),但速度非常慢。另外切换到QOpenGLWidget并不快。
  • 我已经读到QWidget的绘画有时比QGraphicsView更快,但我认为它会为鼠标处理做很多额外的工作。是否有其他类型的实施可能?
  • Bugreport提出的解决方案是一个水平堆叠的场景,旋转90°。这看起来像一个肮脏但可行的选择。但后来我想用更多鼠标交互来实现更复杂的场景,并且被迫翻译每个坐标将是开发和调试的真正痛苦。然而,它表明GraphicsView通常能够承担这种复杂性。
  • 是否可以实现某种类型的平铺,其中项目根据可见区域动态地附加和删除场景?这会提高渲染速度吗?有没有我可以学习的示例代码?

我很感谢有关此错误的任何意见和建议。

最小代码示例:

C ++ Qt示例,最初发布在https://bugreports.qt.io/browse/QTBUG-11059

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>

int main( int argc, char *argv[] )
{
QApplication app( argc, argv );

QGraphicsScene s;
QGraphicsScene s2;

for( int i=0;i<40000;i++ ) {
    QGraphicsRectItem *ri = new QGraphicsRectItem( 0, 0, 40, 20 );
    ri->setPos( 0, i*25 );
    s.addItem( ri );
    ri = new QGraphicsRectItem( 0, 0, 20, 40 );
    ri->setPos( i*25, 0 );
    s2.addItem( ri );
}
QGraphicsView v;
v.setWindowTitle( "BAD" );
v.setScene( &s );
v.show();
QGraphicsView v2;
v2.setWindowTitle( "GOOD" );
v2.rotate( 90 );
v2.setScene( &s2 );
v2.move( v.pos()+QPoint(v.width()+20,0) );
v2.show();

return app.exec();
}

我的(稍微复杂一点)Python3 / PyQt5例子:

我正在使用Linux64,Python 3.4.3(Anaconda 2.3.0),Qt 5.5

import random
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys


class  Track(QGraphicsObject):
    def __init__(self, pos=QPointF(),width=800,):
        super(Track, self).__init__()
        self.topleft = pos
        self.setPos(self.topleft)
        self.width= width
        self.height = 20
        self.pressed = False

        #caching boundingrect and shape improves speed
        self.br = QRectF(0,0,self.width+1,self.height+1)
        self.sh = QPainterPath()
        self.sh.addRect(0, 0, self.width, self.height)

    def mousePressEvent(self, event):
            self.pressed = not self.pressed
            self.update()
            super(Track, self).mousePressEvent(event)

    def boundingRect(self):
        return self.br

    def shape(self):
        return self.sh

    def paint(self, painter, option, widget):
        painter.setPen(QPen(Qt.black,0))
        if self.pressed:
            painter.setBrush(Qt.darkGreen)
        else:
            painter.setBrush(Qt.lightGray)
        painter.drawRect(0, 0,self.width,self.height)


class TrackView(QGraphicsView):
    def __init__(self):
        super(TrackView, self).__init__()
        self.gs = QGraphicsScene(self)
        self.setScene(self.gs)
        self.tracks = []
        for i in range(100000):
            rect = Track(QPointF(10,i*30))
            self.tracks.append(rect)
            self.gs.addItem(rect)
        self.gs.setSceneRect(0,0,1200,self.tracks[-1].topleft.y()+50)
        self.resize(1200,800)

def main():
    app = QApplication(sys.argv)
    view = TrackView()
    view.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

编辑:我找到了解决方法 Qt似乎与GraphicsScene有问题,高度&gt;&gt;宽度(高而窄)。解决方案是将sceneRect设置为width = height并禁用水平滚动条。 IE浏览器。 self.gs.setSceneRect(0,0,1200,self.tracks[-1].topleft.y()+50)变为self.gs.setSceneRect(0,0,3000050,3000050)

0 个答案:

没有答案