Trying to make an SDL widget in QT4 using SDL_WINDOWID but cannot get the widget to show

I am trying to create an SDL drawing canvas inside a simple QT4 window following the below information in the SDL wiki and another question on this site. The project is an NES emulator using QT and SDL and we decided that we decided to try building.

I currently have a main_window class that will contain the SDL widget, menus that I have created, and possibly other stuff as the project progresses. The SDL widget I am creating is called rom_canvas and inherits from QWidget. So far, I can set the SDL_WINDOWID environment variable and it looks like I can interact with widgets where I can set and get my geometry and see that it is actually "visible" but nothing appears in the windows.

I have no experience with QT4 and SDL so far, and I have no experience with C ++, so I might be missing something obvious.

Here's the rom_canvas class:

#include "rom_canvas.hpp"
#include <iostream>
#include <cstdlib>
#include <QString>

rom_canvas::rom_canvas(QWidget *parent)
 : QWidget(parent)
{
 parent->setAttribute(Qt::WA_PaintOnScreen);
 parent->setAttribute(Qt::WA_OpaquePaintEvent);
// setAttribute(Qt::WA_PaintOnScreen);
// setAttribute(Qt::WA_OpaquePaintEvent);

 setUpdatesEnabled(false);

 // a hack I found online to get the SDL surface to appear in our own window
 QString id;
 id.setNum(parent->winId());
    setenv("SDL_WINDOWID", id.toAscii().data(), 1);
 SDL_InitSubSystem(SDL_INIT_VIDEO);

 resize(320, 240);

 // change constants later
 sdl_screen = SDL_SetVideoMode(320, 240, DEFAULT_BPP, SDL_SWSURFACE);

 if(!sdl_screen)
  std::cout << "couldn't create screen" << std::endl;

 SDL_LockSurface(sdl_screen);
 SDL_FillRect(sdl_screen, NULL, 0x00FF0000);
 SDL_UnlockSurface(sdl_screen);
 SDL_UpdateRect(sdl_screen, 0, 0, 0, 0);
}

rom_canvas::~rom_canvas()
{
 // do NOT release sdl_screen here; that done when SDL_Quit() is called in main().
}

// this method is a protected slot
void rom_canvas::test()
{
 std::cout << "rom_canvas test" << std::endl;
 SDL_LockSurface(sdl_screen);
 SDL_FillRect(sdl_screen, NULL, 0x00FF0000);
 SDL_UnlockSurface(sdl_screen);
 SDL_UpdateRect(sdl_screen, 0, 0, 0, 0);
}

      

And here's the main_window constructor:

main_window::main_window(QWidget *parent)
 : QMainWindow(parent)
{
 canvas = new rom_canvas(this);
 setCentralWidget(canvas);
 canvas->setGeometry(100, 100, 100, 100);
 canvas->show();
 canvas->update();

 // Add File Menu
 open_action = new QAction(tr("&Open..."), this);
 open_action->setShortcuts(QKeySequence::Open);
 open_action->setStatusTip(tr("Open a new ROM"));
 connect(open_action, SIGNAL(triggered()), this, SLOT(select_rom()));

 exit_action = new QAction(tr("E&xit"), this);
 exit_action->setStatusTip(tr("Exit nesT"));
 connect(exit_action, SIGNAL(triggered()), /*QApplication::instance()*/canvas, SLOT(/*quit()*/test()));
 // Remember to change this back!!

 file_menu = menuBar()->addMenu(tr("&File"));
 file_menu->addAction(open_action);
 file_menu->addAction(exit_action);

 rom_dir = QDir::homePath();
}

      

The code is a little messy as I was trying to get this to work. Any help is of course greatly appreciated.

+2


source to share


2 answers


I think you already know, but the SDL_WINDOWID trick is probably not portable - I'm pretty sure it won't work on Mac. I'm curious if you want to use SDL in this scenario - if you just want a pixel-address buffer (or multiple) to use QPixmap / QImage and stick to pure Qt. Or, if you want to use SDL sprite features, I would suggest using SDL composition for an in-memory buffer attached to a QImage, and then drawing it as a Qt widget. (Or use QImages as sprites and use the OpenGL QPainter backend)



Internally, Qt works quite hard using platform-based code to convert the image format, so while it sounds pretty heavy, I think it will be fast enough and more reliable and portable than the SDL_WINDOWID trick.

0


source


So, I think I got at least something. After playing around with the code for a bit, I ended up commenting out the methods setAttribute

at the top of the file and it seems to work. Also, the method setUpdatesEnabled

didn't seem to have an impact, so I removed it since I had it there when I tried to get it to work.

Below is a picture of this in action. I don't have the code to update the surface yet, so I have to select a menu item to draw it now. It looks like the menu bar is cutting out the top of the surface, so I'll have to figure out how to change it later.



Hope this helps someone.

SDL canvas http://img18.imageshack.us/img18/3453/nestsdl.png

0


source







All Articles