首次启动后,SDL 窗口中没有背景

No background in SDL window after first launch

提问人:lem0nify 提问时间:10/29/2023 最后编辑:genpfaultlem0nify 更新时间:11/2/2023 访问量:43

问:

我有一个简单的 C 程序,使用 SDL2:

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

int main(int argc, char** argv) {
  if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
    return 1;
  }

  SDL_Window* window = SDL_CreateWindow(
      "Hello, SDL2!",
      SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
      200, 400,
      SDL_WINDOW_SHOWN
  );

  if (window == NULL) {
    const char* error_message = SDL_GetError();
    printf("error creating window: %s\n", error_message);
    SDL_Quit();
    return 1;
  }

  SDL_Surface* surface = SDL_GetWindowSurface(window);
  if (surface == NULL) {
    const char* error_message = SDL_GetError();
    printf("surface is NULL. error: %s\n", error_message);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 1;
  }

  if (SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 0, 255, 0)) != 0) {
    const char* error_message = SDL_GetError();
    printf("FillRect failed. error: %s\n", error_message);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 1;
  }
  
  if (SDL_UpdateWindowSurface(window) != 0) {
    const char* error_message = SDL_GetError();
    printf("UpdateWindowSurface failed. error: %s\n", error_message);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 1;
  }

  SDL_Delay(2000);

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

在第一次启动时,我看到了一个绿色背景的窗口,但之后每个启动窗口都是完全透明的,没有报告任何错误。这就是我所看到的:enter image description here

它实际上不是透明的,它只是将窗口后面的像素作为背景。如果我稍微移动一下,就会发生这种情况:

enter image description here

我还尝试用其他编程语言(Zig)重写相同的代码,并且行为是相同的:在第一次启动时,我再次看到一个绿色窗口,但在每次下一次启动时,它都以相同的方式出现错误。

我的系统是 Archlinux,桌面是 X11 上的 KDE/Plasma。这种行为的原因可能是什么?

更新:添加事件循环对这种情况没有帮助。

c 事件处理 SDL-2

评论

3赞 HolyBlackCat 10/29/2023
如果没有事件循环,有些平台就无法正确绘制,无论如何,您迟早会需要它。去读一读。SDL_PollEvent()
0赞 lem0nify 10/29/2023
@HolyBlackCat我知道事件循环以及如何实现它,但我对为什么会发生这种情况以及为什么在首次启动时不会发生的原因感兴趣。那么这是一个已知问题吗?
0赞 HolyBlackCat 10/29/2023
我以前没有看到这种确切的行为(重新启动后的不同行为),但我确实看到一个窗口没有在没有事件循环的情况下呈现东西。我不认为这本身是 SDL2 错误。
1赞 HolyBlackCat 10/29/2023
您是否在事件循环中重绘?
2赞 HolyBlackCat 10/29/2023
如果这是一个游戏,你应该连续重绘,每秒 X 次。如果这不是游戏,您可以尝试在没有事件时阻止,并在到达时重新绘制。SDL_WaitEvent()SDL_WINDOWEVENT_EXPOSED

答:

0赞 lem0nify 11/2/2023 #1

正如@HolyBlackCat评论中提到的,如果没有事件循环,可能存在图形错误,事件循环不仅必须存在,而且还必须包括更新窗口表面。

SDL_Event evt;
while (1) {
  if (SDL_PollEvent(&evt) != 0) {
    if (e.type == SDL_QUIT) {
      break;
    } else if (e.type == SDL_WINDOWEVENT) {
      if (e.window.event == SDL_WINDOWEVENT_EXPOSED) {
        SDL_UpdateWindowSurface(window);
      }
    }
  }
}