C++ SDL2:打开第二个窗口后键盘输入失效(单窗口模式正常)
问题分析与解决方案
你的问题其实很好定位——你只处理了SDL_QUIT事件,却完全忽略了窗口关闭的SDL_WINDOWEVENT_CLOSE事件。
为什么单窗口正常、多窗口失效?
在单窗口模式下,部分SDL版本或Linux桌面环境会在唯一窗口被关闭时,自动触发SDL_QUIT事件,让你的程序能正常退出。但当存在多个窗口时,SDL不会因为单个窗口关闭就发送SDL_QUIT——这个事件只有在所有窗口都关闭,或者系统发出全局退出请求(比如某些桌面环境的全局快捷键)时才会触发。所以你点击任意一个窗口的关闭按钮,程序根本没收到退出信号,自然会继续运行。
修复代码
只需要在你的事件循环里添加对SDL_WINDOWEVENT_CLOSE的处理即可。下面是修改后的事件循环部分:
while (Run) { while (SDL_PollEvent (&Event)) { // 处理全局退出请求 if (Event.type == SDL_QUIT) { Run = false; } // 处理单个窗口的关闭按钮事件 else if (Event.type == SDL_WINDOWEVENT) { if (Event.window.event == SDL_WINDOWEVENT_CLOSE) { // 这里可以选择两种逻辑: // 1. 只要有一个窗口关闭就退出整个程序(直接设Run为false) Run = false; // 2. 关闭对应窗口并继续运行其他窗口(需要给Window类加状态标记,比如isActive,然后在Refresh时判断是否跳过) } } } W1.Refresh (); W2.Refresh (); SDL_Delay (1000 / 60); }
额外的优化建议
除了修复核心问题,还有几个小细节可以优化:
- 合并SDL初始化调用:你现在重复调用了四次
SDL_Init,其实可以一次性初始化所有需要的子系统,这样更简洁也更易维护:if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) { cerr << "SDL初始化失败: " << SDL_GetError() << "\n"; return 1; } - 添加Renderer创建失败的错误处理:在
Window::Init里,你只检查了窗口创建失败的情况,但如果Renderer创建失败(比如GPU不支持),会导致后续Refresh时访问空指针崩溃。可以加上:if (UseGPU) { Renderer = SDL_CreateRenderer(W, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE); if (Renderer == NULL) { cerr << "Renderer创建失败: " << SDL_GetError() << "\n"; SDL_DestroyWindow(W); return 1; } }
内容的提问来源于stack exchange,提问作者RPBCACUEAIIBH
相关产品推荐
相关产品推荐

