在QML插件的QGLWidget上渲染QImage

kar*_*lip 4 c++ opengl qt qt4 qml

我正在尝试编写一个QML插件,它从视频中读取帧(使用自定义小部件来完成该任务,而不是QtMultimedia/Phonon),每个帧都转换为QImageRGB888,然后显示在a QGLWidget(出于性能原因) .现在屏幕上没有任何东西,屏幕始终保持白色.

重要的是要声明我已经完成了所有这些工作QGLWidget,所以我知道问题是设置和绘制QGLWidget.

该插件正在注册:

qmlRegisterType<Video>(uri,1,0,"Video");
Run Code Online (Sandbox Code Playgroud)

Video插件的主要类也是如此.在它的构造函数上我们有:

Video::Video(QDeclarativeItem* parent)
: QDeclarativeItem(parent), d_ptr(new VideoPrivate(this))
{    
    setFlag(QGraphicsItem::ItemHasNoContents, false);            

    Q_D(Video);
    QDeclarativeView* view = new QDeclarativeView;
    view->setViewport(&d->canvas()); // canvas() returns a reference to my custom OpenGL Widget
}
Run Code Online (Sandbox Code Playgroud)

在我跳转到canvas对象之前,让我说我重载Video::paint()所以它canvas.paint()QImage作为参数传递时调用,我不知道这是否是正确的方法,所以我想对此提出一些建议:

void Video::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    Q_UNUSED(painter);
    Q_UNUSED(widget);
    Q_UNUSED(option);

    Q_D(Video);
    // I know for sure at this point "d->image()" is valid, but I'm hiding the code for clarity
    d->canvas().paint(painter, option, d->image());
}
Run Code Online (Sandbox Code Playgroud)

canvas对象声明为,GLWidget canvas;并且此类的标头定义为:

class GLWidget : public QGLWidget
{
    Q_OBJECT
public:        
    explicit GLWidget(QWidget* parent = NULL);
    ~GLWidget();

    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QImage* image);
};
Run Code Online (Sandbox Code Playgroud)

看起来很简单.现在,执行QGLWidget如下:

GLWidget::GLWidget(QWidget* parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
   // Should I do something here?
   // Maybe setAutoFillBackground(false); ???
}

GLWidget::~GLWidget()
{
}
Run Code Online (Sandbox Code Playgroud)

最后:

void GLWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QImage* image)
{
   // I ignore painter because it comes from Video, so I create a new one:
   QPainter gl_painter(this);


   // Perform drawing as Qt::KeepAspectRatio

   gl_painter.fillRect(QRectF(QPoint(0, 0), QSize(this->width(), this->height())), Qt::black);

   QImage scaled_img = image->scaled(QSize(this->width(), this->height()), _ar, Qt::FastTransformation);

   gl_painter.drawImage(qRound(this->width()/2)  - qRound(scaled_img.size().width()/2),
                        qRound(this->height()/2) - qRound(scaled_img.size().height()/2),
                        scaled_img); 
}
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

我最初在Qt论坛上问了这个问题,但没有回复.

kar*_*lip 5

解决了.问题是当我应该从加载它的应用程序中检索GL上下文时,我试图在我的插件中创建一个新的GL上下文.

这段代码非常有助于理解如何实现这一目标.

顺便说一句,我发现这些东西正在被吸引进去view.这只是我需要执行view->show(),但这创建了另一个窗口,这不是我想要的.我上面分享的链接有答案.

  • [这里是](https://gitorious.org/peregrine/peregrine/blobs/master/qml-plugin/videooutput/qmlvideo.cpp) (2认同)