【问题标题】:cant get SDL2 event's from window无法从窗口获取 SDL2 事件
【发布时间】:2018-02-16 11:55:01
【问题描述】:

我尝试在 C++ 中学习 SDL。我有一个简单的程序,它会显示一个图像。但是当我尝试通过单击窗口上的关闭按钮来关闭窗口时,什么也没有发生。

这是我的代码:-

#include <SDL2/SDL.h>
int main(int argc,char **argv)
{
    static int k =0;
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window *w;
    w = SDL_CreateWindow("SDL VS Works",300,300,400,500,SDL_WINDOW_OPENGL);

    SDL_Renderer *render = SDL_CreateRenderer(w,-1,SDL_RENDERER_ACCELERATED);

    SDL_Surface *tux  = SDL_LoadBMP("res/tux.bmp");

    SDL_Texture *texture = SDL_CreateTextureFromSurface(render,tux);
    SDL_FreeSurface(tux);
    SDL_ShowWindow(w);
    SDL_Event event;

    while(1)
    {
        k++;
        printf("Running and loop %d\'th\n",k);
        SDL_PollEvent(&event);
        if(event.type == SDL_QUIT)
        {
            printf("closing \n");
            goto sos;
        }
        SDL_RenderCopy(render,texture,0,0);
        SDL_RenderPresent(render);
        SDL_Delay(1000);

    }


sos:
    SDL_DestroyWindow(w);
    SDL_DestroyRenderer(render);
    SDL_DestroyTexture(texture);

    SDL_Quit();
}

我在 Arch Linux 上使用 g++ 7.3。

【问题讨论】:

  • 与您的问题无关,但不要在循环中使用gotobreak
  • 另请注意,您需要检查SDL_PollEvent 返回的内容。通常通过将其作为循环中的条件。
  • @Someprogrammerdude 当代码变大时,我将使用 goto to sos: 当我想退出时。
  • @Someprogrammerdude 谢谢 :)
  • 它对我来说很好用。单击关闭按钮结束循环。也许它没有收到退出消息,因为您让线程休眠 1000 毫秒并且它没有响应或其他什么,或者您在释放按钮之前移动了鼠标。尝试删除 SDL_Delay() 行并尝试查看。

标签: c++ events event-handling sdl-2


【解决方案1】:

SDL 在内部使用事件队列。当 any 事件发生时,例如鼠标移动几个像素,它会被添加到队列中。当您轮询事件时(使用SDL_PollEvent),您只会获得最旧的事件。其他所有内容都在队列中。

由于您的代码每秒仅轮询一次,因此队列可能会被鼠标移动淹没,而 SDL_QUIT 事件只是排队等候,深入队列。

您通常想要做的是在循环中轮询事件。请注意,SDL_PollEvent 在没有待处理事件时返回 0。

while (SDL_PollEvent(&event)) {
    if(event.type == SDL_QUIT)
    {
        //...
    }
}

【讨论】:

  • 感谢删除 SDL_pollevent 解决了问题,但现在 CPU 使用率太高了
  • 删除SDL_PollEvent?我将假设您的意思是SDL_Delay,因为这确实会导致 CPU 完全使用。您不必消除延迟。如果你使用我写的循环遍历队列中的每个事件,SDL_QUIT 将在SDL_Delay 返回时立即被捕获。
  • @noone 保持SDL_Delay,将SDL_PollEvent放入嵌套循环中,将睡眠减少到100左右。
【解决方案2】:

顺便说一下,循环应该是这样的:

SDL_Event SDLEvent;

    while (SDL_PollEvent(&SDLEvent))
    {
        switch (SDLEvent.type)
        {
        case SDL_QUIT: break;
        case SDL_WINDOWEVENT: break;
        case SDL_MOUSEMOTION: break;
        case SDL_MOUSEWHEEL: break;
        }
    }

是像这样的 switch 语句还是像你这样的 if 语句并不重要。如果队列中仍有事件,SDL_PollEvents 将返回 1,否则返回 0。通过在 while 条件内调用 SDL_PollEvents(&SDLEvent),它将在进入下一个 while 块之前处理队列中的所有事件。

有趣的是,您的窗口无法关闭的问题似乎与其他问题有关,因为它对我有用。我已经提到过可能去掉 SDL_Delay 线,看看它是否有任何作用;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    相关资源
    最近更新 更多