2

我正在尝试在一个简单的 QT4 窗口内创建一个 SDL 绘图画布,遵循SDL wiki中提供的信息和本网站上的另一个问题。该项目是一个使用 QT 和 SDL 的 NES 模拟器,我和朋友决定尝试创建它。

目前,我有一个 main_window 类,它将包含 SDL 小部件、我设置的菜单以及项目开发过程中可能的其他内容。我正在创建的 SDL 小部件称为 rom_canvas,它继承自 QWidget。到目前为止,我能够设置 SDL_WINDOWID 环境变量,并且我似乎能够与小部件进行交互,因为我可以设置并获取它的几何形状并看到它实际上是“可见的”,但实际上没有任何东西显示在窗户。

到目前为止,我对 QT4 和 SDL 没有任何经验,也没有大量的 C++ 经验,所以我可能会遗漏一些明显的东西。

这是 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);
}

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

代码有点乱,因为我一直在尝试让它工作。任何帮助当然都非常感谢。

4

2 回答 2

0

所以我想我至少可以展示一些东西。在玩了一会儿代码之后,我最终注释掉了setAttribute文件顶部的方法,它似乎正在工作。此外,该setUpdatesEnabled方法似乎没有影响,所以我删除了它,因为我只是在试图让它工作时才把它放在那里。

下面是它的图片。我还没有代码来刷新表面,所以我现在必须选择一个菜单选项来绘制它。菜单栏似乎正在切掉表面的顶部,所以我必须在以后弄清楚如何重新定位它。

希望这可以帮助某人。

SDL 画布 http://img18.imageshack.us/img18/3453/nestsdl.png

于 2009-09-29T22:56:47.353 回答
0

我想你已经知道了,但是 SDL_WINDOWID 技巧可能是不可移植的——我很确定它不会在 Mac 上工作。在这种情况下,我很好奇您想要 SDL 做什么 - 如果您只是想要一个像素可寻址的图像缓冲区(或多个),请使用 QPixmap / QImage 并坚持使用纯 Qt。或者,如果您想要 SDL sprite 功能,我建议将 SDL 合成到附加到 QImage 的内存缓冲区中,然后将其绘制到 Qt 小部件。(或者使用 QImages 作为精灵,并使用 OpenGL QPainter 后端)

在内部,Qt 非常努力地使用平台原生代码进行图像格式转换,所以即使这听起来相当繁重,我认为它会足够快,并且比 SDL_WINDOWID 技巧更健壮和可移植。

于 2009-10-16T07:18:19.203 回答