首页 > 解决方案 > 为什么我的窗口只有在我使用 SDL_PollEvent() 后才会显示?

问题描述

我在 C 中使用 SDL2 并想在屏幕上显示一些东西而不需要输入。但是当我运行代码以呈现黑屏时,窗口不会打开。我继续做我知道会让它弹出并添加一个SDL_Event变量并使用SDL_PollEvent(). 我想知道为什么我必须这样做,以及是否有办法让我使用 aSDL_Window而无需轮询任何事件。

(例如:类似动画的东西)。

有问题的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>

int main()
{
    if (SDL_Init(SDL_INIT_VIDEO))
    {
        fprintf(stderr, "Error while Initalizing SDL2: %s\n", SDL_GetError());
        return EXIT_FAILURE;
    }
    SDL_Window *window = SDL_CreateWindow("Connect Four", 100, 100, 500, 500, SDL_WINDOW_SHOWN);
    if (!window)
    {
        fprintf(stderr, "Error while Initalizing window: %s\n", SDL_GetError());
        return EXIT_FAILURE;
    }
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (!renderer)
    {
        SDL_DestroyWindow(window);
        fprintf(stderr, "Error while Initalizing renderer: %s\n", SDL_GetError());
        return EXIT_FAILURE;
    }
    SDL_Event events; //without these two lines
    SDL_PollEvent(&events); //the window will not open on screen
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);    
    SDL_RenderPresent(renderer);
    SDL_Delay(3000);

    SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_SUCCESS;
}

标签: csdl-2

解决方案


这可能会令人困惑,因为一些 SDL 示例(包括 SDL doc wiki)使用“draw&delay”代码而没有事件处理,但这不是在屏幕上显示内容的可靠方式。这些示例过于简化,并且是很久以前编写的,当时它有点工作,但仅用于最简单的事情,因为 3 秒可能不足以让窗口管理器杀死无响应的程序,或者让用户注意到窗口图像崩溃,如果它是被其他窗口最小化或覆盖。

对您的问题的简短回答是否定的,您的程序必须与窗口管理器通信(旁注 -在某些操作系统/图形系统上可能不需要);您必须获取事件并对特殊窗口事件做出反应(例如,您的窗口变得可见或用户请求调整大小)。在 SDL 中,这是通过call 完成的,它在内部进行此通信并生成您可以稍后检查的事件队列,因此您需要经常调用它,直接或间接通过orSDL_PumpEventsSDL_PollEventSDL_WaitEvent. 如果你不这样做,窗口管理器可能不会对你好 - 根据窗口管理器,你可能会得到“应用程序没有响应,让我们杀死它”对话框,灰色的窗口,或者像你的情况一样,根本没有窗口(这种特殊情况是因为您在收到“您的窗口现在可见”事件之前已经呈现了渲染结果,因此您的图像被丢弃;这就是为什么在渲染之前处理事件会改变事情的进展)。

但即便如此,处理事件一次也不正确。你所拥有的仍然是乐观的“让我们希望在 3 秒内不会发生任何破坏”。如果你做动画,处理每一帧的事件;但如果您有静态显示代码 - 将其视为动画也可能是个好主意。基本上,您需要渲染循环,在开始时进行事件处理,并在必要时重绘代码以重新生成图像。这种“必须”可能是无条件的(每次迭代都完全重绘),或者,如果你真的不想这样做(例如,出于处理成本的原因——大多数 GUI 程序在空闲时不会完全重绘)你仍然必须当窗口管理器说您以前的图像不再有效时重绘 - SDL 通过SDL_WindowEventSDL_WINDOWEVENT_EXPOSED类型通知您。SDL_WaitEvent以避免不必要的迭代。


推荐阅读