在 QML 插件的 QGLWidget 上渲染 QImage
我正在尝试编写一个 QML 插件,它从视频中读取帧(使用自定义小部件来完成该任务,而不是 QtMultimedia/Phonon),并且每个帧都转换为 QImage
RGB888,然后显示在 QGLWidget
上(出于性能原因).现在什么都没有画到屏幕上,屏幕一直保持白色.
I'm trying to write a QML plugin that reads frames from a video (using a custom widget to do that task, NOT QtMultimedia/Phonon), and each frame is converted to a QImage
RGB888, and then displayed on a QGLWidget
(for performance reasons). Right now nothing is draw to the screen and the screen stays white all the time.
重要的是要说明我已经在没有 QGLWidget
的情况下完成了所有这些工作,所以我知道问题在于设置和绘制 QGLWidget.
It's important to state that I already have all of this working without QGLWidget
, so I know the issue is setting up and drawing on QGLWidget.
插件正在注册:
qmlRegisterType<Video>(uri,1,0,"Video");
所以 Video
是插件的主类.在它的构造函数上,我们有:
so Video
is the main class of the plugin. On it's constructor we have:
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
}
在我跳转到 canvas
对象之前,让我说我重载了 Video::paint()
所以它调用了 canvas.paint()
在传递 QImage
作为参数时,我不知道这是否是正确的方法,所以我想对此提出一些建议:
Before I jump to the canvas
object, let me say that I overloaded Video::paint()
so it calls canvas.paint()
while passing QImage
as parameter, I don't know if this is the right way to do it so I would like some advice on this:
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());
}
canvas
对象声明为GLWidget canvas;
,该类的头部定义为:
The canvas
object is declared as GLWidget canvas;
and the header of this class is defined as:
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget* parent = NULL);
~GLWidget();
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QImage* image);
};
看起来很简单.现在,QGLWidget
的实现如下:
Seems pretty simple. Now, the implementation of QGLWidget
is the following:
GLWidget::GLWidget(QWidget* parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
// Should I do something here?
// Maybe setAutoFillBackground(false); ???
}
GLWidget::~GLWidget()
{
}
最后:
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);
}
我错过了什么?
我最初在 Qt 论坛上问 这个问题,但没有得到任何答复.
I originally asked this question on Qt Forum but got no replies.
推荐答案
已解决.问题是当我应该从加载它的应用程序中检索 GL 上下文时,我试图在我的插件中创建一个新的 GL 上下文.
Solved. The problem was that I was trying to create a new GL context within my plugin when I should be retrieving the GL context from the application that loaded it.
此代码是非常有帮助了解如何做到这一点.
This code was very helpful to understand how to accomplish that.
顺便说一句,我发现这些东西是在 view
中绘制的.只是我需要执行 view->show()
,但这会创建另一个窗口,这不是我想要的.我上面分享的链接有答案.
By the way, I discovered that the stuff was being draw inside view
. It's just that I needed to execute view->show()
, but that created another window which was not what I was looking for. The link I shared above has the answer.
相关文章