WhyCan Forum

人过留名,雁过留声,感谢各位朋友不离不弃地支持。 QQ: 516333132, 微信: whycan_cn (哇酷网/挖坑网/填坑网) admin@whycan.cn

您尚未登录。

#1 2019-11-18 11:49:10

qter
会员
注册时间: 2017-09-14
累计积分: 25

我试一试Qt widgets 窗口嵌入 SDL2窗口

在Qt上使用SDL2绘制QWidget: https://www.kurukurumi.com/blog/?post=54

离线

#2 2019-11-18 11:51:57

qter
会员
注册时间: 2017-09-14
累计积分: 25

Re: 我试一试Qt widgets 窗口嵌入 SDL2窗口

在Qt上使用SDL2绘制QWidget: https://www.kurukurumi.com/blog/?post=54



通过SDL2的SDL_CreateWindowFrom函数将QWidget转换为SDL_Window。

SDL_Window *window = SDL_CreateWindowFrom((void*)this->winId())

        Qt只能在QWidget的paintEvent事件里进行绘图。

virtual void QWidget::paintEvent(QPaintEvent* event);

        源码如下:

/*
    File   : SDL2Widget.h
    Author : hubenchang0515@outlook.com
    Blog   : www.kurukurumi.com
*/
 
#ifndef SDL2WIDGET_H
#define SDL2WIDGET_H
 
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <QWidget>
#include <QPaintEvent>
 
class SDL2Widget : public QWidget
{
    Q_OBJECT
public:
    SDL2Widget(QWidget* parent=0);
    ~SDL2Widget();
protected:
    void paintEvent(QPaintEvent* event);
     
private:   
    SDL_Window *window;
    SDL_Renderer *render;
    SDL_Surface *surface;
    SDL_Texture *texture;
};
#endif

SDL2Widget.cpp:

/*
    File   : SDL2Widget.cpp
    Author : hubenchang0515@outlook.com
    Blog   : www.kurukurumi.com
*/
 
#include <SDL2Widget.h>
 
SDL2Widget::SDL2Widget(QWidget* parent):QWidget(parent)
{
    /* SDL2初始化 */
    SDL_Init(SDL_INIT_EVERYTHING);
    /* 把QWidget转换为SDL_Window */
    window = SDL_CreateWindowFrom((void*)this->winId());
    /* SDL2 Image初始化 */
    IMG_Init(IMG_INIT_PNG);
    /* 加载图片,创建surface */
    surface = IMG_Load("demo.jpg");
}
 
SDL2Widget::~SDL2Widget()
{
 
}
 
/* 绘图操作必须在paintEvent事件里进行 */
void SDL2Widget::paintEvent(QPaintEvent* event)
{
    /* 在window上创建一个render */
    render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED 
                        | SDL_RENDERER_PRESENTVSYNC);
    /* 创建一个texture */
    texture = SDL_CreateTextureFromSurface(render, surface);
    /* 清空render的内容 */
    SDL_RenderClear(render);
    /* 将texture复制到render上 */
    SDL_RenderCopy(render, texture, NULL, NULL);
    /* 将render显示到window上 */
    SDL_RenderPresent(render);
    SDL_RenderPresent(render); //我的电脑上,需要调用两次才能显示出来,原因不明
    /* 销毁render和texture,释放内存 */
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(render);
 
}

main.cpp:

/*
    File   : main.cpp
    Author : hubenchang0515@outlook.com
    Blog   : www.kurukurumi.com
*/
 
#include <QApplication>
#include <SDL2Widget.h>
#include <QLayout>
#include <QPushButton>
 
int main(int argc,char* argv[])
{
    QApplication app(argc,argv);
    QVBoxLayout* layout = new QVBoxLayout;
    SDL2Widget* sdlWidget = new SDL2Widget;
    QPushButton* button = new QPushButton("Button");
    layout->addWidget(sdlWidget);
    layout->addWidget(button);
    QWidget w;
    w.setLayout(layout);
    w.show();
    w.resize(640,400);
    QObject::connect(button,&QPushButton::clicked,
        sdlWidget,(void(SDL2Widget::*)(void))&SDL2Widget::repaint);
    return app.exec();
}

        运行结果:
1480522974492453.png

离线

#3 2019-11-18 11:52:54

qter
会员
注册时间: 2017-09-14
累计积分: 25

Re: 我试一试Qt widgets 窗口嵌入 SDL2窗口

几经折腾, 上面的代码跑是能跑, 但是图片要么不显示, 要么会闪, Ubuntu和Win7都测试过。

离线

#4 2019-11-18 17:14:14

qter
会员
注册时间: 2017-09-14
累计积分: 25

Re: 我试一试Qt widgets 窗口嵌入 SDL2窗口

离线

#5 2019-11-18 17:16:58

qter
会员
注册时间: 2017-09-14
累计积分: 25

Re: 我试一试Qt widgets 窗口嵌入 SDL2窗口

找到一个7年前 qt 调用 ffmpeg 解码到 sdl2 的demo: https://github.com/zackxue/videoPlayer/blob/master/qtsdl2.cpp

应该可以借鉴一下吧。

离线

#6 2019-11-19 16:09:07

qter
会员
注册时间: 2017-09-14
累计积分: 25

Re: 我试一试Qt widgets 窗口嵌入 SDL2窗口

http://qaru.site/questions/1199981/sdl2-rendering-into-qwidget

试了一下这个demo, 可以用



QWidget中的SDL2渲染


我正在寻找我在GTK2和SDL1.2,QT5和SDL2.0.3中编写的仿真器端口。到目前为止,这还不错,因为仿真器在SDL2中独立工作,而图形界面在QT中也可以正常工作,两者都可以交互。我的问题是尝试在QWidget中获取SDL2。这是在使用窗口黑客方法的SDL1.2中正常工作的方法。

从我在Internet上阅读的所有内容中,都可以使用从QT小部件SDL_CreateWindowFrom接收winId()并将其传递给它的函数来禁用此功能。但是,这类似于使用openGL时的情况。

我想知道当im仅使用标准SDL2绘图功能获取纹理而不使用OpenGL时如何执行此操作。到目前为止,我所有的尝试都失败了,并且SDL根本没有出现在小部件中。

另外,我知道您可以将SDL_Suface转换为QImage。每次更新QImage(每秒60帧)时,如何开始更新QT Widget。这样做的复杂性在于QT和SDL在单独的线程中工作。

如果有人对方向有所了解,请指出我或一些有用的代码示例,这些示例可以得出答案,我将不胜感激。我尚未提供代码,因为我不确定如何执行此操作以提供任何代码。

EDIT
因此,在使用SDL和QT进行了一些测试之后。我设法使用标准绘画工具获得了用于在QWidget中进行绘画的SDL2。但是,这仅在将渲染器设置为时有效SDL_RENDERER_SOFTWARE。如果我尝试使用SDL_RENDERER_ACCELERATED,我也会尝试。这导致以下事实:QT窗口被完全阻止,无法绘制任何内容(包括窗口中的所有其他小部件),并最终由于不响应操作系统而终止(在我的测试案例中为Kubuntu)。

是否有人对为什么会这样有任何想法。SDL_RENDERER_ACCELERATED当SDL2绘制到由SDL_CreateWindow和创建的窗口中时,我可以完美地使用它SDL_CreateRenderer。这是在QWidget上绘制时的唯一问题。

这是我仍然拥有的代码:

main.cpp

#include "mainwindow.h"
#include <QApplication>
#include <SDL2/SDL.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = SDL_CreateWindowFrom((void*)w.ptr_gfx->winId());
    SDL_Renderer* render = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);

    SDL_SetRenderDrawColor(render, 255, 0, 0, 255);
    SDL_RenderFillRect(render, NULL);
    SDL_RenderPresent(render);

    return a.exec();

    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(render);
    SDL_Quit();
}

主窗口 mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ptr_gfx = ui->gfx;
    ui->gfx->setUpdatesEnabled(false);
}

MainWindow::~MainWindow()
{
    delete ui;
}

主窗口 mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    Ui::MainWindow *ui;
    QWidget* ptr_gfx;
};

#endif // MAINWINDOW_H

界面文件 mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QWidget" name="gfx" native="true">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>10</y>
      <width>191</width>
      <height>131</height>
     </rect>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>400</width>
     <height>20</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

离线

#7 2019-11-19 16:58:22

qter
会员
注册时间: 2017-09-14
累计积分: 25

Re: 我试一试Qt widgets 窗口嵌入 SDL2窗口

qt_sdl.gif

Qt 操作 SDL 生成色块,并显示到 QImage 控件。

离线

#8 2019-11-19 17:21:48

qter
会员
注册时间: 2017-09-14
累计积分: 25

Re: 我试一试Qt widgets 窗口嵌入 SDL2窗口

qt_sdl_2.gif

随机颜色和载入图片都可以了。

离线

#9 2019-11-19 18:40:44

小智
会员
注册时间: 2019-10-16
累计积分: 19

Re: 我试一试Qt widgets 窗口嵌入 SDL2窗口

离线

#10 2019-11-20 10:52:56

qter
会员
注册时间: 2017-09-14
累计积分: 25

Re: 我试一试Qt widgets 窗口嵌入 SDL2窗口

qt_sdl_3.gif

Linux 小改了一下, 跑一跑 OK

离线

页脚