[Development] How fast grab a QML item's content to image when it updates?

Konstantin Tokarev annulen at yandex.ru
Tue Dec 12 14:40:50 CET 2017



12.12.2017, 16:13, "Denis Shienkov" <denis.shienkov at gmail.com>:
> 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
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development

-- 
Regards,
Konstantin



More information about the Development mailing list