【问题标题】:QGraphicsScene is calling QGraphicsItem paint event all the timeQGraphicsScene 一直在调用 QGraphicsItem 绘制事件
【发布时间】:2016-02-29 20:23:36
【问题描述】:

我有一个QWidget,它持有一个QGraphicsScene 和几个项目。其中一些项目是QGraphicsRectItems 和子类QGraphicsItems。当场景中只有QGraphicsRectItems 时,应用程序的性能很好,处理器使用率正常,在 0% - 10% 之间。但是当我将QGraphicsItems 添加到场景中时,总是会调用绘制事件,这使得处理器使用率上升到 50% - 70%,有时应用程序会冻结。

当我将 QGraphicsView viewUpdateMode 设置为 QGraphicsView::NoViewportUpdate 时,处理器使用情况很好,同时使用 QGraphicsItems 和 QGraphicsRectItems,但是当 viewUpdateMode 设置为 QGraphicsView::FullViewportUpdate、QGraphicsView::MinimalViewportUpdate 或 QGraphicsView::BoundingRectViewportUpdate 时循环调用 QGraphicsItem 中的绘制事件,即使场景中没有任何修改。

这是我创建QGraphicsScene的方式,QGrpahicsView是这样的。

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);

而子类QGraphicsItem是这样的:

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();
   }

所以问题是,我如何才能使绘制事件仅在场景中有任何修改或场景中的任何对象时才被调用,并且没有 QGraphicsScene 一直在调用 QGraphicsItem 绘制事件?

【问题讨论】:

  • 欢迎来到 SO... 您有什么问题?对于只是浏览文本的人来说,可能看不出你在问什么。
  • 哦,对不起,我忘了问题,我会编辑文本添加它
  • 您真的需要打开mouseTracking 吗?这可能是这里的一个问题,并且可能是持续更新的原因。
  • 其实这不是必须的,这只是我在做一个测试来检查行为,但是有没有它,在这种情况下性能是一样的
  • 您似乎正在尝试实现与QGraphicsItemGroup 类似的功能。您在这里不使用 QGraphicsItemGroup 有什么原因吗?

标签: c++ qt qgraphicsview qgraphicsitem qgraphicsscene


【解决方案1】:

你可以使用caching:

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

【讨论】:

  • 我刚刚解决了。我有一个子类 QGraphicsPixmapItem 覆盖了绘制事件。我刚刚删除了这个被覆盖的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多