简体   繁体   中英

Why isn't SDL_CreateWindow showing a window when called from another class?

Rewriting this to try to provide some clarity and update the code with some things that have changed.

I am restructuring a project that used SDL2, and have encountered issues trying to create a blank window. I have attempted to structure the project similarly to the original by separating all functionality dealing with SDL_Window into its own class. If I move the call to SDL_CreateWindow into the same class as the event loop or move the event loop to the same class as the window, the window is created and shown as expected, however as it is now, the window appears to be created successfully (SDL_CreateWindow is not returning NULL) and the program doesn't seem to be hanging, but it does not display a window while the program is running.

The SDL_Window is created in the Graphics class and stored in a member variable:

Graphics::Graphics(const char* title, unsigned int w, unsigned int h, unsigned int flags, int& status) {
    screen = SDL_CreateWindow(title,
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        w, h,
        flags);
    
    status = 0;
    if (screen == NULL)
        status = 1;
}

Graphics is instantiated in the Window class and stored in a member variable.

Window::Window(const char* title, unsigned int w, unsigned int h, unsigned int flags, int& status) {
    g = Graphics(title, w,h, flags, status);
}

Window is instantiated in main, and if the window is created successfully, it starts the event loop.

{
    int status;
    Window window("Mirari", 640,480, SDL_WINDOW_SHOWN, status);
    
    if (status == 0) {
        window.eventLoop();
    } else {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window and renderer: %s", SDL_GetError());
        return 1;
    }
}

The event loop itself to be thorough (update and draw are both currently empty functions).

void Window::eventLoop() {
    SDL_Event ev;
    
    bool running = true;
    while (running) {
        const int start_time = SDL_GetTicks();
        
        while (SDL_PollEvent(&ev)) {
            switch (ev.type) {
                case SDL_QUIT:
                    running = false;
                    break;
                default:
                    break;
            }
        }
        
        //update();
        //draw();
        std::cout << "." << std::endl;
        
        const int elapsed = SDL_GetTicks() - start_time;
        
        if (elapsed < 1000 / FPS)
            SDL_Delay(1000 / FPS - elapsed);
    }
}

SDL is initialized with this static function and these flags.

void Window::init(unsigned int sdl_flags, IMG_InitFlags img_flags) {
     SDL_Init(sdl_flags);
     IMG_Init(img_flags);
     TTF_Init();
}
...
Window::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER, IMG_INIT_PNG);

I know that a window can be created in a separate class because the first version of this project did that and it worked, I'm just not sure what has changed that is causing the window not to show up.

As said by some programmer dude , you design is not perfect and should be thought again.

Nevertheless, from what we can see on your code : If the Window constructor is called (and the SDL_Init was called before, which I assume so), then the windows should be created.

From there we only can guess what we can't see (as it's not part of what you are displaying) :

  • is the definition of SDL_WINDOWPOS_UNDEFINED, the same in both context ?
  • is the screen variable definition the same in both context ?
  • is the "screen" used in "update", or "draw" method, and, as uninitialized : it fails
  • ... ?

As you probably are new to development, I suggest you adopt this habit very early : your code should check and report everything it does. A good program is easy to debug, as it says what's wrong

For instance, just after :

screen = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
    w, h, flags);

you may want to write something like :

if(!screen)
{
    std::cout << "Failed to create window\n";
    return -1;
}

or better :

if(!screen)
{
    throw std::exception("Failed to create window\n");
}

And so on.

For instance, in your function update, you may want to have something like :

if(!screen)
{
    throw std::exception("Unable to update the display as it is uninitialized\n");
}

I assume your application would not end without any comment... but that's a guess

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM