SDL2渲染到QT窗口

1、什么是SDL

 

2、SDL视频显示流程如下:

3、SDL视频显示函数

SDL_Init():            初始化SDL系统
SDL_CreateWindow():    创建窗口 SDL_Window
SDL_CreateRenderer():  创建渲染器 SDL_Renderer
SDL_CreateTexture():   创建纹理 SDL_Texture
SDL_UpdateTexture():   设置纹理的数据
SDL_RenderClear():     清除渲染器的内容
SDL_RenderCopy():      将纹理的数据拷贝给渲染器
SDL_RenderPresent():   显示
SDL_Delay():           工具函数,用于延时。
SDL_Quit():            退出SDL系统

4、SDL数据结构

SDL_Window:        代表了一个“窗口”
SDL_Renderer:      代表了一个“渲染器”
SDL_Texture:       代表了一个“纹理”
SDL_Rect:          一个简单的矩形结构

5、QT实现

5.1 UI设计

在UI中拖入一个label 重命名为videoLabel

 更改大小为400*300

 6、代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <SDL.h>
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    //重载
    void timerEvent(QTimerEvent *ev) override;
    int testSDL();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"
#include <QApplication>
#include <QDebug>



//报错提示,需要加入这个文件
#define __STDC_CONSTANT_MACROS

extern "C"{
//指定函数是c语言函数,函数名不包含重载标注
//引用ffmpeg头文件
    #include <libavcodec/avcodec.h>
    #include <libavdevice/avdevice.h>
    #include <libavformat/avformat.h>
    #include <libavutil/avconfig.h>
    #include <libswscale/swscale.h>
    #include <libswresample/swresample.h>
//引入SDL2的头文件
    #include <SDL.h>
}
//在头文件的下面要加入这条语句:#undef main,这是因为SDL中的 SDL_main.h已经定义了main
#undef main
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    //显示当前ffmpeg的版本号--用来测试环境是否搭建成功
    qDebug() << av_version_info();
/*测试代码*/
//    if(SDL_Init(SDL_INIT_VIDEO)){
//        qDebug() << "Could not initialize SDL"<<SDL_GetError();
//    }else{
//        qDebug() <<"Success init SDL";
//    }

   return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
//绘制图像
#include <QPainter>
//使用QPaint绘制QImage
#include <QImage>
//定义窗口大小
static int sdl_width = 0;
static int sdl_height = 0;

//SDL 窗口
static SDL_Window *sdl_win = NULL;
//渲染器
static SDL_Renderer *sdl_render = NULL;
//材质
static SDL_Texture *sdl_texture = NULL;
//存放材质的地方
static unsigned char *rgb = NULL;
//像素的大小
static unsigned int pix_size = 4;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    sdl_width = ui->videoLabel->width();
    sdl_height = ui->videoLabel->height();
    //改变窗口大小
    //resize(sdl_width,sdl_height);
    testSDL();
}

MainWindow::~MainWindow()
{
    delete ui;
}
//定时器
void MainWindow::timerEvent(QTimerEvent *ev)
{
    static unsigned char tmp = 255;
    tmp--;
    for (int j = 0; j < sdl_height; j++)
    {
        int b = j * sdl_width * pix_size;
        for (int i = 0; i < sdl_width*pix_size; i += pix_size)
        {
            rgb[b + i] = 0;           //B
            rgb[b + i + 1] = 0;       //G
            rgb[b + i + 2] = tmp;     //R
            rgb[b + i + 3] = 0;       //A
        }
    }
    //5 内存数据写入材质
    SDL_UpdateTexture(sdl_texture, NULL, rgb, sdl_width * pix_size/*一行的大小*/);
    //6 清理屏幕
    SDL_RenderClear(sdl_render);
    SDL_Rect sdl_rect;
    sdl_rect.x = 0;
    sdl_rect.y = 0;
    sdl_rect.w = sdl_width;
    sdl_rect.h = sdl_height;
      //7 复制材质到渲染器
    SDL_RenderCopy(sdl_render, sdl_texture,
        NULL,//原图位置和尺寸
        &sdl_rect//目标位置和尺寸
    );
    //8 渲染
    SDL_RenderPresent(sdl_render);
}

int MainWindow::testSDL()
{
    /*******************************SDL*************************************/
        //1 初始化SDL video库
        if (SDL_Init(SDL_INIT_VIDEO))
        {
             //qDebug() << SDL_GetError();
            return -1;
        }
        //2 生成SDL并渲染到QT的label
        //ui->videoLabel->winId():代表窗口句柄
        sdl_win = SDL_CreateWindowFrom((void*)ui->videoLabel->winId());
        if (!sdl_win)
        {
            //qDebug() << SDL_GetError();
            return -2;
        }

        //3 生成渲染器
        sdl_render = SDL_CreateRenderer(sdl_win/*SDL 窗口*/, -1/*渲染指定的设备 -1:使用默认的*/, SDL_RENDERER_ACCELERATED/*渲染类型:硬件加速*/);
        if (!sdl_render)
        {
            //qDebug() << SDL_GetError();
            return -3;
        }
        //4 生成材质,材质大小要和控件label大小一致
        sdl_texture = SDL_CreateTexture(
            sdl_render/*渲染器*/,
            SDL_PIXELFORMAT_ARGB8888/*像素格式*/,
            SDL_TEXTUREACCESS_STREAMING/*渲染格式:可加锁*/,
            sdl_width/*宽,根据label进行创建的*/,
            sdl_height/*高*/
        );
        if (!sdl_texture)
        {
            //qDebug() << SDL_GetError();
            return -4;
        }
        //申请图像的数据控件
        rgb = new unsigned char[sdl_height*sdl_width*4];
        //开启定时器
        startTimer(10);

}

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要在Qt中嵌入SDL2窗口,首先需要进行一些准备工作。首先,确保已经安装了QtSDL2,并且你的项目是一个Qt项目。 在Qt项目中,创建一个新的Qt窗口类,例如“MainWindow”,并在该类的构造函数中进行初始化。如下所示: ``` MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { // 设置窗口标题等 // 创建一个QWidget,作为SDL2窗口的父容器 QWidget *sdlContainer = new QWidget(this); setCentralWidget(sdlContainer); // 获取SDL窗口的句柄 SDL_Window *sdlWindow = SDL_CreateWindowFrom((void *)sdlContainer->winId()); } ``` 在上面的代码中,我们首先创建一个QWidget作为SDL2窗口的父容器,并将其设置为主窗口的中心窗口。然后,我们使用Qt的winId()函数获取sdlContainer的窗口句柄,并将其传递给SDL_CreateWindowFrom函数,从而创建一个SDL窗口。 接下来,我们可以将SDL渲染渲染到这个窗口中。我们需要在主窗口类中添加一个paintEvent事件,用于处理窗口重绘。如下所示: ``` void MainWindow::paintEvent(QPaintEvent *event) { // 在窗口重绘时,将SDL渲染器绘制到窗口SDL_Renderer *sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0); SDL_RenderClear(sdlRenderer); // 在这里进行SDL渲染器的渲染操作,例如绘制图形、绘制图片等 SDL_RenderPresent(sdlRenderer); // 调用父类的绘图事件处理函数 QMainWindow::paintEvent(event); } ``` 在上面的代码中,我们创建一个SDL渲染器,并在paintEvent事件中进行渲染操作。请注意,在窗口重绘之前,需要先清除渲染器,然后再进行绘制操作,最后调用SDL_RenderPresent函数将渲染结果显示到窗口上。 通过以上步骤,你可以在Qt中成功嵌入SDL2窗口并进行渲染操作。记得在程序结束时要释放SDL的资源,以避免内存泄漏。 ### 回答2: 将Qt框架与SDL2窗口嵌入可以通过以下步骤实现: 首先,在Qt应用程序中创建一个QWidget对象。例如,可以使用QMainWindow或QDialog来创建一个窗口。 接下来,使用QNativeWindow类将QWidget转换为原生的窗口句柄。可以通过调用QWidget的winId()函数来获取窗口的原生句柄。 然后,使用SDL_CreateWindowFrom函数将窗口的原生句柄传递给SDL2库以创建一个与Qt窗口相关联的SDL窗口。这样,SDL窗口就会嵌入到Qt窗口中。 在创建SDL窗口后,我们可以使用SDL_Renderer以及其他SDL函数来在SDL窗口中绘制图形、处理输入事件等操作。 最后,需要在Qt应用程序的事件循环中处理SDL2窗口的事件。通过使用QObject::startTimer()函数,我们可以将SDL2窗口的事件与Qt应用程序的事件循环相集成,以确保正确地处理事件。 在嵌入SDL2窗口时,还要注意一些限制。由于SDL2和Qt的事件处理机制不同,需要进行一些额外的处理,以确保事件正确传递和处理。另外,还需要注意窗口尺寸、位置等方面的调整,以确保SDL2窗口正确地嵌入到Qt窗口中。 总之,通过以上步骤,我们可以成功地在Qt应用程序中嵌入SDL2窗口,并实现与SDL2相关的图形和输入处理。这种嵌入方式可以帮助我们在使用Qt框架的同时,获得SDL2库强大的图形和输入能力,以满足特定应用需求。 ### 回答3: 要将Qt嵌入SDL2窗口,需要进行以下步骤: 1. 首先,确保已安装好QtSDL2,并准备好Qt项目开发环境。 2. 创建一个Qt窗口应用程序项目,选择“Widgets应用程序”类型。 3. 在Qt的主窗口设计界面中,添加一个QWidget小部件作为SDL2窗口的容器。 4. 将SDL2窗口嵌入到QWidget容器中,可以通过使用SDL_CreateWindowFrom函数或者SDL2函数来实现。 5. 创建一个QTimer对象,在定时器的槽函数中通过SDL_RenderPresent函数或者SDL2函数来绘制SDL2窗口。 6. 编写Qt程序的其他逻辑,包括处理用户输入、更新SDL2窗口内的内容等。 7. 构建和运行Qt程序,即可看到SDL2窗口嵌入到Qt窗口中的效果。 需要注意的是,SDL2和Qt都是强大的图形库,彼此之间的使用存在一定的复杂性和潜在的冲突。在嵌入过程中可能会遇到一些问题,如窗口大小和信号传递等方面的兼容性问题。因此,在实际应用中需要仔细评估项目需求和技术复杂度,并进行充分的测试和调试,以确保嵌入的正确性和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值