tags:

views:

796

answers:

2

Hi all! I'm trying to create an SDL drawing canvas inside of a simple QT4 window, following the information provided in the SDL wiki and in another question on this site. The project is an NES emulator using QT and SDL that a friend and I decided we wanted to try creating.

Currently, I have a main_window class that will contain the SDL widget, menus that I set up, and probably other stuff as the project develops. The SDL widget I'm creating is called rom_canvas and inherits from QWidget. So far, I'm able to set the SDL_WINDOWID environment variable and I seem to be able to interact with the widget in that I can set and get its geometry and see that it is in fact "visible", but nothing actually shows up in the window.

I don't have any experience with QT4 and SDL until now and don't have a ton of C++ experience, so I could 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's 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's a bit messy since I've been trying things to get this to work. Any help is of course greatly appreciated.

A: 
Jesse DeGuire
A: 

I guess you already know, but the SDL_WINDOWID trick probably isn't portable - I am pretty sure it won't work on Mac. I am curious what you want SDL for, in this scenario - if you simply want a pixel-addressable image buffer (or several), use QPixmap / QImage and stick to pure Qt. Or if you want the SDL sprite features, I'd suggest having SDL composite to an in-memory buffer attached to a QImage, and then draw that to a Qt widget. (Or use QImages as sprites, and use the OpenGL QPainter backend)

Internally, Qt works pretty hard to use platform-native code to do image format conversion, so even though this sounds fairly copy-heavy, I think it will be sufficiently fast, and much more robust and portable than the SDL_WINDOWID trick.

James Turner
Actually, a few days after I got SDL to show something, we (my friend and I) decided to just use Qt--partially because we were concerned about the WINDOWID trick being "fixed" in the future. I think I'm going try having the sprite subclass from QGraphicsItem and work with a QImage in there. This should work great since it turns out that QImage supports paletted 8-bit images.Thanks for the help and useful info!
Jesse DeGuire