> Did you try QQuickItem::grabToImage?

Of course, it is veeery slowly.


12.12.2017 16:40, Konstantin Tokarev пишет:

12.12.2017, 16:13, "Denis Shienkov" <[email protected]>:
Hi all...

Is it possible to grab a QQuickItem content (e.g. with all sub-items)
when an item changes?
Did you try QQuickItem::grabToImage?

E.g. with widgets I use the following code:

bool MyWidget::event(QEvent *event)
{
      if (event->type() == QEvent::UpdateRequest)
          myGrab();
      return QWidget::event(event);
}

void MyWidget::myGrab()
{
      ...
      QBackingStore *store = backingStore();
      Q_ASSERT(store);

      QPaintDevice *pdev = store->paintDevice();
      const auto image = dynamic_cast<QImage *>(pdev);
      ...
}

it is very fast (as I know)...

But with the QML I got a troubles: I can 'grab' the sourceItem, using
the FBO and private functions, but the fbo::toImage() is too slow (~24
msecs),
and I don't know how to intercept the signal when a watched item updates:

Grabber::Grabber(QQuickItem *parent)
      : QQuickItem(parent)
{
      setFlag(QQuickItem::ItemHasContents);
}

// Where sourceItem - is a watched item.
void Grabber::setSourceItem(QQuickItem *sourceItem)
{
      if (sourceItem == m_sourceItem)
          return;
      m_sourceItem = sourceItem;
      emit sourceItemChanged(m_sourceItem);
      update();
}

QSGNode *Grabber::updatePaintNode(QSGNode *oldNode,
                                    UpdatePaintNodeData *updatePaintNodeData)
{
      Q_UNUSED(updatePaintNodeData);

      if (!m_sourceItem)
          return oldNode;

      QSGRootNode root;
root.appendChildNode(QQuickItemPrivate::get(m_sourceItem)->itemNode());

      const QScopedPointer<QSGRenderer> renderer(
                  QQuickItemPrivate::get(this)->
                  sceneGraphRenderContext()->createRenderer());

      renderer->setRootNode(&root);

      const QSize size(m_sourceItem->width(), m_sourceItem->height());
      renderer->setDeviceRect(size);
      renderer->setViewportRect(size);
      renderer->setProjectionMatrixToRect(QRectF(QPointF(), size));
      renderer->setClearColor(Qt::transparent);

      QOpenGLFramebufferObject fbo(size);
      renderer->renderScene(BindableFbo(&fbo));
      fbo.release();

      QElapsedTimer et;
      et.start();
      const QImage image = fbo.toImage(); // TOO LONG ~24 msec!
      qDebug() << "Elapsed:" << et.elapsed();

      return oldNode;
}

it is very fast (as I know).

But with the QML I got a troubles: I can 'grub' an item, using the FBO,

but the toImage() method is too slow (~24 msecs), and I don't know how

to intercept a signal when the watched item updates:

Grabber::Grabber(QQuickItem *parent)
      : QQuickItem(parent)
{
      setFlag(QQuickItem::ItemHasContents);
}

QSGNode *Grabber::updatePaintNode(QSGNode *oldNode,
                                    UpdatePaintNodeData *updatePaintNodeData)
{
      Q_UNUSED(updatePaintNodeData);

      if (!m_sourceItem)
          return oldNode;

      QSGRootNode root;
root.appendChildNode(QQuickItemPrivate::get(m_sourceItem)->itemNode());

      const QScopedPointer<QSGRenderer> renderer(
                  QQuickItemPrivate::get(this)->
                  sceneGraphRenderContext()->createRenderer());

      renderer->setRootNode(&root);

      const QSize size(m_sourceItem->width(), m_sourceItem->height());
      renderer->setDeviceRect(size);
      renderer->setViewportRect(size);
      renderer->setProjectionMatrixToRect(QRectF(QPointF(), size));
      renderer->setClearColor(Qt::transparent);

      QOpenGLFramebufferObject fbo(size);
      renderer->renderScene(BindableFbo(&fbo));
      fbo.release();

      QElapsedTimer et;
      et.start();
      const QImage image = fbo.toImage(); // TOO LONG!
      qDebug() << "Elapsed:" << et.elapsed();

      return oldNode;
}

_______________________________________________
Development mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/development

_______________________________________________
Development mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/development

Reply via email to