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

Denis Shienkov denis.shienkov at gmail.com
Tue Dec 12 14:17:05 CET 2017


12.12.2017 16:13, Denis Shienkov пишет:
> Hi all...
>
> Is it possible to grab a QQuickItem content (e.g. with all sub-items)
> when an item changes?
>
> 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;
> }
>




More information about the Development mailing list