为什么我的 window 只在我使用 SDL_PollEvent() 后显示?
Why does my window only get shown after I use SDL_PollEvent()?
我在 C 语言中使用 SDL2,并希望在不需要接受输入的情况下在屏幕上显示一些内容。但是当我 运行 显示黑屏的代码时 window 将无法打开。我继续做我知道会让它弹出的事情,并添加了一个 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, 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;
}
这可能会造成混淆,因为一些 SDL 示例(包括 SDL doc wiki)使用没有事件处理的“绘制和延迟”代码,但这不是在屏幕上显示内容的可靠方式。这些示例过于简化,并且是很久以前写的,当时它有点用,但仅用于最简单的事情,因为 3 秒可能不足以让 window 管理器杀死无响应的程序,或者让用户注意到 window 如果图像被最小化或被其他图像覆盖,图像会折叠 windows。
对您问题的简短回答是否定的,您的程序必须与 window 经理沟通(旁注 - 可能 没有必要一些 operating/graphics 系统);您必须获取事件并对特殊 window 事件做出反应(例如,您的 window 变得可见或用户请求调整大小)。在 SDL 中,这是通过 SDL_PumpEvents
调用完成的,它在内部执行此通信并生成您可以稍后检查的事件队列,因此您需要经常调用它,直接或间接通过 SDL_PollEvent
或 SDL_WaitEvent
。如果你不这样做,window 经理可能不会对你好 - 根据 window 经理,你可能会看到“应用程序没有响应,让我们终止它”对话框,灰色显示 window或者,就像您的情况一样,根本没有 window (这种特殊情况是因为您在收到“您的 window 现在可见”事件之前已经呈现了渲染结果,因此您的图像被丢弃;这就是为什么在渲染之前处理事件会改变事情的发展方式。
但即便如此,一次处理事件也是不正确的。你所拥有的仍然是乐观的“让我们希望 3 秒内不会发生任何破坏”。如果你做动画,处理每一帧的事件;但是如果你有静态显示代码——把它当作动画来对待可能是个好主意。基本上你需要渲染循环,在开始时进行事件处理,并在必要时将代码重绘到 re-generate 你的图像。这种“必须”可能是无条件的(每次迭代都完全重绘),或者,如果您真的不想这样做(例如,出于处理成本的原因——大多数 GUI 程序在空闲时不会完全重绘),您仍然必须当 window 经理说您以前的图像不再有效时重绘 - SDL 通过 SDL_WINDOWEVENT_EXPOSED
类型的 SDL_WindowEvent 通知您。在这种情况下,您可能希望使用阻塞 SDL_WaitEvent
来避免不必要的迭代。
我在 C 语言中使用 SDL2,并希望在不需要接受输入的情况下在屏幕上显示一些内容。但是当我 运行 显示黑屏的代码时 window 将无法打开。我继续做我知道会让它弹出的事情,并添加了一个 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, 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;
}
这可能会造成混淆,因为一些 SDL 示例(包括 SDL doc wiki)使用没有事件处理的“绘制和延迟”代码,但这不是在屏幕上显示内容的可靠方式。这些示例过于简化,并且是很久以前写的,当时它有点用,但仅用于最简单的事情,因为 3 秒可能不足以让 window 管理器杀死无响应的程序,或者让用户注意到 window 如果图像被最小化或被其他图像覆盖,图像会折叠 windows。
对您问题的简短回答是否定的,您的程序必须与 window 经理沟通(旁注 - 可能 没有必要一些 operating/graphics 系统);您必须获取事件并对特殊 window 事件做出反应(例如,您的 window 变得可见或用户请求调整大小)。在 SDL 中,这是通过 SDL_PumpEvents
调用完成的,它在内部执行此通信并生成您可以稍后检查的事件队列,因此您需要经常调用它,直接或间接通过 SDL_PollEvent
或 SDL_WaitEvent
。如果你不这样做,window 经理可能不会对你好 - 根据 window 经理,你可能会看到“应用程序没有响应,让我们终止它”对话框,灰色显示 window或者,就像您的情况一样,根本没有 window (这种特殊情况是因为您在收到“您的 window 现在可见”事件之前已经呈现了渲染结果,因此您的图像被丢弃;这就是为什么在渲染之前处理事件会改变事情的发展方式。
但即便如此,一次处理事件也是不正确的。你所拥有的仍然是乐观的“让我们希望 3 秒内不会发生任何破坏”。如果你做动画,处理每一帧的事件;但是如果你有静态显示代码——把它当作动画来对待可能是个好主意。基本上你需要渲染循环,在开始时进行事件处理,并在必要时将代码重绘到 re-generate 你的图像。这种“必须”可能是无条件的(每次迭代都完全重绘),或者,如果您真的不想这样做(例如,出于处理成本的原因——大多数 GUI 程序在空闲时不会完全重绘),您仍然必须当 window 经理说您以前的图像不再有效时重绘 - SDL 通过 SDL_WINDOWEVENT_EXPOSED
类型的 SDL_WindowEvent 通知您。在这种情况下,您可能希望使用阻塞 SDL_WaitEvent
来避免不必要的迭代。