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

查看:65
本文介绍了捕获 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天全站免登陆