2009-09-24 9 views
2

J'essaie de créer un canevas de dessin SDL à l'intérieur d'une fenêtre QT4 simple, en suivant les informations fournies in the SDL wiki et dans une autre question sur ce site . Le projet est un émulateur NES utilisant QT et SDL qu'un ami et moi avons décidé d'essayer de créer.Essayer de créer un widget SDL dans QT4 en utilisant SDL_WINDOWID, mais impossible d'afficher le widget

Actuellement, j'ai une classe main_window qui contiendra le widget SDL, les menus que j'ai mis en place, et probablement d'autres choses au fur et à mesure que le projet se développe. Le widget SDL que je crée s'appelle rom_canvas et hérite de QWidget. Jusqu'à présent, je suis capable de définir la variable d'environnement SDL_WINDOWID et il me semble pouvoir interagir avec le widget en ce que je peux définir et obtenir sa géométrie et voir qu'elle est en fait "visible", mais rien n'apparaît réellement dans la fenêtre.

Je n'ai aucune expérience avec QT4 et SDL jusqu'à présent et je n'ai pas beaucoup d'expérience en C++, donc je pourrais manquer quelque chose d'évident.

est ici la classe rom_canvas:

#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); 
} 

Et voici le constructeur main_window:

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(); 
} 

Le code est un peu en désordre depuis que j'ai essayé des choses pour que cela fonctionne. Toute aide est bien sûr grandement appréciée.

+0

Si vous n'avez pas beaucoup d'expérience en Qt ou SDL, je reviendrai en utilisant les deux. Vous pouvez probablement accomplir ce que vous voulez en utilisant seulement l'un des deux. – thekidder

+0

Je doute que, puisque SDL n'est pas une bibliothèque GUI. Son problème est très intéressant et j'ai eu l'exemple du problème avec Gtkmm. J'ai fini par utiliser Cairo pour dessiner librement dans un Widget. – piotr

Répondre

0

Je suppose que vous savez déjà, mais l'astuce de SDL_WINDOWID est probablement pas portable - Je suis assez sûr que cela ne fonctionnera pas sur Mac. Je suis curieux ce que vous voulez SDL pour, dans ce scénario - si vous voulez simplement un tampon d'image adressable par pixel (ou plusieurs), utilisez QPixmap/QImage et s'en tenir à Qt pur. Ou si vous voulez les fonctionnalités de l'image-objet SDL, je suggérerais d'avoir SDL composite à un tampon en mémoire attaché à un QImage, puis dessiner cela à un widget Qt. (Ou utilisez QImages comme sprites, et utilisez le backend OpenGL QPainter)

En interne, Qt travaille très dur pour utiliser le code natif de la plate-forme pour faire la conversion de format d'image, même si cela semble assez lourd, je pense qu'il être suffisamment rapide, et beaucoup plus robuste et portable que l'astuce SDL_WINDOWID.

+0

En fait, quelques jours après que SDL ait montré quelque chose, nous (mon ami et moi) avons décidé d'utiliser Qt - en partie parce que nous étions préoccupés par le fait que le truc de WINDOWID soit "corrigé" dans le futur. Je pense que je vais essayer d'avoir la sous-classe sprite de QGraphicsItem et travailler avec un QImage là-dedans.Cela devrait fonctionner car il s'avère que QImage supporte les images 8 bits palettisées. Merci pour l'aide et les informations utiles! –

0

Donc, je pense que je l'ai eu au moins afficher quelque chose. Après avoir joué avec le code un petit peu, j'ai fini par commenter les méthodes setAttribute en haut du fichier et cela semble fonctionner. De plus, la méthode setUpdatesEnabled ne semblait pas avoir d'impact, alors j'ai supprimé cela parce que je ne l'avais que pour essayer de le faire fonctionner.

Voici une photo de celui-ci en action. Je n'ai pas encore de code pour rafraîchir la surface, donc je dois sélectionner une option de menu pour la dessiner pour le moment. Il semble que la barre de menu coupe le haut de la surface, donc je vais devoir trouver comment le repositionner plus tard.

J'espère que cela aidera quelqu'un.

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

Questions connexes