[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:53:09 CET 2017
> 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" <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
More information about the Development
mailing list