Python&C++相互混合调用编程全面实战-35重载qt显示视频窗口完成图像设置和视频绘制
原创
©著作权归作者所有:来自51CTO博客作者oxoxwork的原创作品,请联系作者获取转载授权,否则将追究法律责任
作者:虚坏叔叔
早餐店不会开到晚上,想吃的人早就来了!😄
重载qt显示视频窗口完成图像设置和视频绘制
一、创建显示视频窗口OpenGl Widget
打开qt设计师
Qwidget
绘制视频效率低,可以使用OpenGl Widget
。
拖动OpenGl Widget
到窗口,修改名称为view
将打开按钮放到前面:
宽度和高度都调整为600*400
PyPlayer.cpp
中修改视口大小:
if (width > 0 && height > 0)
{
resize(width, height);
ui.view->resize(width, height);
}
为了控制opengl
窗口,需要提升view
二、创建类VideoView用于重载widget
在Visual studio
中添加类VideoView
用于重载widget
修改VideoView.h
#pragma once
#include <QOpenGLWidget>
//Q_OBJECT表示自动会生成信号槽相关代码
class VideoView:public QOpenGLWidget
{
Q_OBJECT
public:
VideoView(QWidget *p = NULL);
~VideoView();
// 重载显示函数
void paintEvent(QPaintEvent *e);
public slots:
void SetImage(unsigned char* rgb); // 槽函数
signals:
void SetImageSig(unsigned char *rgb); // 信号函数
protected:
//存放显示图像
QImage *img = NULL;
};
修改VideoView.cpp
#include "VideoView.h"
#include <QPainter>
void VideoView::SetImage(unsigned char* rgb)
{
if (!rgb)return;
if (!img)
{
/// 本窗口宽度
uchar *buf = new uchar[width()*height() * 4];
// 宽高发生变化需要再次分配空间
img = new QImage(buf, width(), height(), QImage::Format_ARGB32);
}
uchar *bits = img->bits();
memcpy(bits, rgb, width()*height() * 4);
// 刷新显示
update();
}
// 重载显示函数
void VideoView::paintEvent(QPaintEvent *e)
{
if (!img || img->isNull()) return;
QPainter painter;
painter.begin(this);
painter.drawImage(QPoint(0, 0), *img);
painter.end();
}
VideoView::VideoView(QWidget *p):QOpenGLWidget(p)
{
QObject::connect(
this, SIGNAL(SetImageSig(unsigned char*)),
this, SLOT(SetImage(unsigned char*))
);
}
VideoView::~VideoView()
{
}
三、Python调用SetImage实现图像显示
修改pyqt.py
,调用SetImage来在线程中显示图像
isRunning = True
#输出的宽高,根据窗口尺寸
winWidth = 1280
winHeight = 720
#主函数 在子线程中调用,线程是c++创建
def main():
print("Python main")
global ff;
global winWidth;
global winHeight;
while isRunning:
#解封装
re = ff.read()
if re:
print(".", end='', flush = True) #flush输出缓冲
#解码图像
re = ff.decode(winWidth, winWidth)
print(re, end='', flush = True)
#显示图像
if re:
SetImage(ff)
time.sleep(0.02)
else:
time.sleep(1)
修改PyPlayer.cpp
添加函数SetImage
,用于被python调用
#include <Python.h>
#include "PyPlayer.h"
#include <iostream>
#include <QFileDialog>
#include <thread>
#include "PyFFmpeg.h"
#include "XFFmpeg.h"
using namespace std;
static PyObject *pModule = 0;
static VideoView *view = 0;
PyObject *SetImage(PyObject *self, PyObject *arg)
{
PyFFmpeg *obj = (PyFFmpeg *)arg;
view->SetImageSig( obj->ff->rgb);
Py_RETURN_TRUE;
}
这里需要引入PyFFmpeg
头文件路径
由于需要用到rgb
,所以需要在XFFmpeg.h
中,将rgb
改为public变量
在PyPlayer.cpp
构造函数中注册进去,这样python才能g狗调用到
Py_XDECREF(conf);
// 开放选择文件的接口给python
static PyMethodDef meths[] = {
{ "OpenDialog", (PyCFunction)OpenDialog, METH_NOARGS, 0 }
,{ "SetImage", (PyCFunction)SetImage, METH_O, 0 } // 一个参数
,{ NULL }
};
在PyPlayer
类中,需要控制播放器窗口,所以定义一个静态view,然后在构造函数中初始化它:
PyPlayer::PyPlayer(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
view = ui.view;
运行:
四、总结
- 本文重载qt显示视频窗口完成图像设置和视频绘制 。