1

I have a QWidget which is holding a QGraphicsScene with several items. Some of those items are QGraphicsRectItems and subclassed QGraphicsItems. When in the scene there are QGraphicsRectItems only, the performance of the application is fine and the processor usage is normal, between 0% - 10%. But when I add to the scene the QGraphicsItems, the paint event is always being called, and that makes the processor usage raises to 50% - 70% and sometimes the application gets frozen.

When I set the QGraphicsView viewUpdateMode to QGraphicsView::NoViewportUpdate, then the processor usage is fine, with both QGraphicsItems and QGraphicsRectItems, but when the viewUpdateMode is set to QGraphicsView::FullViewportUpdate, QGraphicsView::MinimalViewportUpdate or QGraphicsView::BoundingRectViewportUpdate then the paint event in QGraphicsItem is called in a loop, even if there's no modification on the scene.

This is the way I create the QGraphicsScene and the QGrpahicsView is like this.

scene = new QGraphicsScene();
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
scene->setSceneRect(0, 0, 470, 720);

view = new QGraphicsView(scene);
view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);    
view->setMouseTracking(true);

And the subclassed QGraphicsItem is like this:

MyItem::MyItem(QGraphicsItem *parent)
: QGraphicsItem(parent),
  mIsHover(false), mIsSelected(false)
{
    pixmapItem1 = new QGraphicsPixmapItem(this);
    pixmapItem2 = new QGraphicsPixmapItem(this);
    textItem = new QGraphicsTextItem(this);

    pixmapItem1->setParentItem(this);
    pixmapItem2->setParentItem(this);
    textItem->setParentItem(this);
    textItem->setTextWidth(60);

    this->setAcceptTouchEvents(true);
    this->setAcceptDrops(true);
    this->setAcceptHoverEvents(true);
    this->setAcceptedMouseButtons(Qt::LeftButton);  

    this->setFlag(QGraphicsItem::ItemIsSelectable);
    this->setFlag(QGraphicsItem::ItemIsMovable);
    this->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
    this->setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
 }

 QRectF MyItem::boundingRect() const
 {
       QRectF rect = this->childrenBoundingRect();

       return rect;
  }

  void MyItem::paint(QPainter* painter, const QStyleOptionGraphicsItem*  opt,QWidget* wdgt)
  {
        qDebug() << "-> MyItem::pain()";

        painter->setClipRect(this->boundingRect());

        if(this->mIsHover || this->mIsSelected){
           painter->setBrush(QColor(Qt::green));
           painter->setPen(Qt::black);
           painter->drawRect(this->boundingRect());

        }else{
           painter->setBrush(Qt::transparent);
           painter->setPen(Qt::NoPen);
           painter->drawRect(this->boundingRect());
        }
   }
   void MyItem::hoverEnterEvent(QGraphicsSceneHoverEvent*)
   {
       qDebug()  << Q_FUNC_INFO;
       this->mIsHover = true;
       this->update();
   }

   void MyItem::hoverLeaveEvent(QGraphicsSceneHoverEvent*)
   {
       qDebug() << Q_FUNC_INFO;
       this->mIsHover = false;
       this->update();
   }

so the question is, how can I do to make the paint event being called only when there is any modification in the scene, or in any object on the scene, and not having the QGraphicsScene being calling QGraphicsItem paint event all the time?

Angie Quijano
  • 4,167
  • 3
  • 25
  • 30
Agm
  • 11
  • 4
  • Welcom to SO... What's your question? For someone just skimming the text it might not apparent what you are asking. – lhcgeneva Nov 26 '15 at 17:00
  • 1
    Oh, sorry, I forgot the question, I'll edit the text to add it – Agm Nov 26 '15 at 17:03
  • Do you really need [mouseTracking](http://doc.qt.io/qt-5/qwidget.html#mouseTracking-prop) turned on? This is possibly an issue here and could be the cause of the continuous updates. – TheDarkKnight Nov 26 '15 at 17:07
  • In fact, that's not necessary, it was just a test I was doing to check the behaviour, but with or without it, the performance is the same in this case – Agm Nov 26 '15 at 17:09
  • It looks like you're trying to implement similar functionality to [QGraphicsItemGroup](http://doc.qt.io/qt-5/qgraphicsitemgroup.html). Is there a reason why you're not using QGraphicsItemGroup here? – TheDarkKnight Nov 26 '15 at 17:15
  • How many items do you add to the scene so that the processor goes crazy? @Agm – Alexander Tyapkov Nov 27 '15 at 07:51
  • The total items in the scene is 22 items, but I don't think that's the main problem, because the scene shouldn't be repainting all the time while there is no modification on it, as it happens when the scene contains QGraphicsRectItems only, where the scene is only repainted when any QGraphicsRectItem is hovered or clicked with the mouse. – Agm Nov 29 '15 at 00:08
  • I will try using QGraphicsItemGroup and see what happens. I will tell you, thanks. – Agm Nov 29 '15 at 00:09
  • I have found the cause that is making paint event being called all the time, and it is a subclassed QGraphicsPixmapItem with its paint event overriden. How can I avoid this while overriding QGraphicsPixmapItem paint event? – Agm Nov 30 '15 at 20:57
  • It's solved. I just removed the overriden paint method. – Agm Nov 30 '15 at 22:16

1 Answers1

0

You could use caching:

// Put this in the constructor of your QGraphicsItem
setCacheMode( QGraphicsItem::DeviceCoordinateCache );
// or
setCacheMode( QGraphicsItem::ItemCoordinateCache);
paceholder
  • 1,064
  • 1
  • 10
  • 21
  • I just solved it. I had a subclassed QGraphicsPixmapItem with the paint event overriden. I just removed this overriden method. – Agm Apr 30 '16 at 11:52