捕获QML绘图缓冲区,而不显示 [英] Capture QML drawing buffer, without displaying

查看:313
本文介绍了捕获QML绘图缓冲区,而不显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要抓取每个QML(QtQuick 2)图纸框架并通过网络发送. 目前,我使用了下面列出的方法,但是该方法有两个很大的缺点

I need to grab each QML (QtQuick 2) drawing frame and sent it over the network. At the moment I have used method listed below, but this method has two big disadvantage

1)由于Qt5文档,grabWindow()函数存在性能问题

1) Due to Qt5 documentation grabWindow() function has performance issues

2)它不能与隐藏的QML窗口一起使用

2) It can't work with hidden QML window

是否可以在QQuickWindow :: afterRendering之后获得OpenGL渲染缓冲区? 使用FBO?共享的OpenGL上下文?

Is it possible to get OpenGL render buffer right after QQuickWindow::afterRendering ? Using FBOs ? Shared opengl context ?

class Grab: public QObject
{
 public:
 Grab( QQuickWindow * wnd ) : wnd_(wnd) {}

 public slots:

    void Grabme()
    {
       QImage image = wnd_->grabWindow();
    }

private:

QQuickWindow *wnd_;
};

int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);


QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/grab1/main.qml"));
viewer.showExpanded();

Grab grab( &viewer );
QObject::connect( &viewer, &QtQuick2ApplicationViewer::frameSwapped,
                  &grab, &Grab::Grabme, Qt::DirectConnection );


return app.exec();
}

推荐答案

下面的示例可以将任何qml内容捕获到FBO,然后通过信号将其作为Image发送. 这种方法的唯一问题是可见性,必须成功看到抓取窗口.如果有人知道如何防止这种情况,您可以帮助我并提供更高级的方法.

Example bellow can grab any qml content to FBO and then sent it as Image via signal. Only one problem of this approach is visibility, grab window must be visible for successful grabbing. If anybody knows how to prevent this you can help me and provide more advanced approach.

// main.cpp
int main(int argc, char* argv[])
{
  QApplication app(argc, argv);

  GrabWindow grab;
  grab.setResizeMode( QQuickView::SizeViewToRootObject );
  grab.setSource( QUrl::fromLocalFile("qml/main.qml") );
  grab.setFlags( Qt::Popup );

  grab.show();
  return app.exec();
}


// grabwindow.hpp
#pragma once
#include <QOpenGLFramebufferObject>
#include <QScopedPointer>
#include <QQuickView>
#include <QImage>

class GrabWindow: public QQuickView
{
  Q_OBJECT

signals:
     void changeImage( const QImage &image );

public:
    GrabWindow( QWindow * parent = 0 );

private slots:
    void afterRendering();
    void beforeRendering();

private:
    QScopedPointer<QOpenGLFramebufferObject> fbo_;
};

// grabwindow.cpp
#include "grabwindow.hpp"
#include <limits>

GrabWindow::GrabWindow( QWindow * parent ) :
    QQuickView( parent )
{
  setClearBeforeRendering( false );
  setPosition( std::numeric_limits<unsigned short>::max(), std::numeric_limits<unsigned short>::max() );

  connect( this, SIGNAL( afterRendering()  ), SLOT( afterRendering()  ), Qt::DirectConnection );
  connect( this, SIGNAL( beforeRendering() ), SLOT( beforeRendering() ), Qt::DirectConnection );
}

void GrabWindow::afterRendering()
{
  if( !fbo_.isNull() )
  {
    emit changeImage( fbo_->toImage() );
  }
}

void GrabWindow::beforeRendering()
{
  if (!fbo_)
  {
        fbo_.reset(new QOpenGLFramebufferObject( size(), QOpenGLFramebufferObject::NoAttachment) );
        setRenderTarget(fbo_.data());
  }
}

这篇关于捕获QML绘图缓冲区,而不显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆