1
votes

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?

1
Welcom to SO... What's your question? For someone just skimming the text it might not apparent what you are asking.lhcgeneva
Oh, sorry, I forgot the question, I'll edit the text to add itAgm
Do you really need mouseTracking turned on? This is possibly an issue here and could be the cause of the continuous updates.TheDarkKnight
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 caseAgm
It looks like you're trying to implement similar functionality to QGraphicsItemGroup. Is there a reason why you're not using QGraphicsItemGroup here?TheDarkKnight

1 Answers

0
votes

You could use caching:

// Put this in the constructor of your QGraphicsItem
setCacheMode( QGraphicsItem::DeviceCoordinateCache );
// or
setCacheMode( QGraphicsItem::ItemCoordinateCache);