为什么仅在使用SDL_PollEvent之后才显示窗口?

问题描述

我在C语言中使用SDL2,希望在屏幕上显示某些内容而无需输入。但是,当我运行代码以显示黑屏时,窗口无法打开。我继续做我知道会弹出的事情,并添加了一个SDL_Event变量并使用了SDL_PollEvent()。我想知道为什么必须这样做,以及是否有一种方法可以使用SDL_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,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,255);
    SDL_RenderClear(renderer);    
    SDL_RenderPresent(renderer);
    SDL_Delay(3000);

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

解决方法

这可能会造成混淆,因为某些SDL示例(包括SDL doc Wiki)使用“绘制并延迟”代码而不进行事件处理,但这不是在屏幕上显示内容的可靠方法。该示例过于简化,是很久以前写的,只是为了最简单的事情而编写,因为3秒可能不足以使窗口管理器杀死无响应的程序,或者用户注意到窗口图像崩溃(如果这样)。最小化或被其他窗口覆盖。

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

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...