我正在尝试在简单的QT4窗口内创建SDL绘图画布,遵循提供的信息in the 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();
}
代码有点凌乱,因为我一直在尝试让它发挥作用。任何帮助当然非常感谢。
答案 0 :(得分:0)
所以我认为我至少可以展示一些东西。在稍微玩了一下代码之后,我最终评论了文件顶部的setAttribute
方法,它似乎正在运行。此外,setUpdatesEnabled
方法似乎没有影响,所以我删除了,因为我只是在那里试图让它工作。
下面是它的实际情况。我还没有代码刷新表面,所以我必须选择一个菜单选项来绘制它。看起来菜单栏正在关闭表面顶部,所以我将不得不弄清楚如何重新定位它。
希望这有助于某人。
SDL canvas http://img18.imageshack.us/img18/3453/nestsdl.png
答案 1 :(得分:0)
我猜你已经知道了,但是SDL_WINDOWID技巧可能不可移植 - 我很确定它在Mac上不起作用。我很好奇你想要SDL,在这种情况下 - 如果你只想要一个像素可寻址的图像缓冲区(或几个),使用QPixmap / QImage并坚持使用纯Qt。或者如果你想要SDL精灵功能,我建议将SDL复合到连接到QImage的内存缓冲区,然后将其绘制到Qt小部件。 (或者使用QImages作为精灵,并使用OpenGL QPainter后端)
在内部,Qt非常难以使用平台本机代码进行图像格式转换,因此即使这听起来相当复杂,我认为它足够快,并且比SDL_WINDOWID技巧更加强大和可移植。