且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

捕获QML绘图缓冲区,而不显示

更新时间:2022-03-13 20:57:04

下面的示例可以将任何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());
  }
}