重复关键事件阻塞

发布于 2024-10-20 10:03:13 字数 778 浏览 6 评论 0原文

我用 SFMLOpenGL 编写了一个简单的程序,它绘制了一个旋转的正方形,可以使用箭头键在屏幕上移动。

它在我测试过的所有 Linux 和 Mac 计算机上运行良好,但当我尝试在 Windows 上移动方块(按住箭头键)时,它会移动一小段距离,然后停止移动和旋转。我很确定程序陷入了 GetEvent 方法 - 我的猜测是,当我按住按键足够长的时间以使其开始重复时,事件堆栈会不断添加新事件在我可以将所有内容弹出之前(如果我将 Windows 上的按键重复率降至最低,那么问题就会消失 - 但我不太喜欢这种解决方案)。

我发现按住 Alt、Ctrl、Delete、Page up、Page down、Home、End 等也会导致此行为(即使我没有专门检测程序中的任何这些键),但所有字母键,以及空格键、回车键、退格键和键盘箭头键都可以正常工作(即,如果我按住它们太久,它们不会导致程序暂停)。

我没有确切的代码(我刚刚关闭了笔记本电脑),但它看起来像:

while(running) {
    while(app.GetEvent(event))
        if(event.Type==sf::Event::Closed) running=false;
    if(input.IsKeyDown(sf::Key::Right)); // move right
    // etc etc
    // update rotation
    // draw everything
}

关于确切的问题可能是什么以及如何解决它的任何想法?

I wrote a simple program with SFML and OpenGL which draws a spinning square that can be moved around the screen with the arrow keys.

It works fine on all the Linux and Mac computers I've tested it on, but when I try to move the square on Windows (by holding down an arrow key) it moves a small distance and then stops moving and spinning. I'm pretty sure the program is getting stuck in the GetEvent method - my guess is that when I've held the key down long enough for it to start repeating, the event stack keeps getting new events added to it before I can pop everything off it (and if I turn the key repeat rate on Windows right down to the minimum then the problem goes away - I don't really like this as a solution though).

I found that pressing and holding Alt, Ctrl, Delete, Page up, Page down, Home, End etc all cause this behavior too (even though I don't specifically detect any of these keys in the program), but all the letter keys, as well as space, enter, backspace and the keypad arrow keys work fine (i.e. they don't cause the program to pause if I hold them down for too long).

I don't have the exact code (I just turned my laptop off), but it looks like:

while(running) {
    while(app.GetEvent(event))
        if(event.Type==sf::Event::Closed) running=false;
    if(input.IsKeyDown(sf::Key::Right)); // move right
    // etc etc
    // update rotation
    // draw everything
}

Any ideas as to what the exact problem might be, and how I could fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

呆橘 2024-10-27 10:03:13

我知道这是一个老问题,但我想回答这个问题,以便帮助其他可能遇到类似问题的人。

SFML 1.6 有两种获取用户输入的方法。一种是基于事件的,您可以处理通过 sf::Window::GetEvent() 发送给您的每个事件。另一种是基于查询的,您可以直接检查窗口的 sf::Input 类。

您在这里使用了基于查询的方法,但将其放入事件循环中,这并不是它真正的预期使用方式。它本来就是要这样使用的。这是一个很好的功能,因为 SFML 本质上会自动为您保留一个布尔键表,因此您无需自己管理键状态。恕我直言,使用重复输入会更优雅,因为您不会向事件队列发送垃圾邮件,而只需检查布尔值。

while(app.GetEvent(event))
    if(event.Type == sf::Event::Closed) running=false;
    if(event.Type == sf::Event::KeyPressed && event.Key.Code == sf::Key::Right)
    {
      // move right
    }
}

如果您只想直接查询 sf::Input ,那么您可以使用与上面相同的代码,但将其放在事件循环之外。

while(app.GetEvent(event)
{
}

if (myWindow.GetInput().IsKeyDown(sf::Key::Right))
{
}

默认情况下,应为 sf::Windows 启用自动按键重复,但您可以使用 sf::Window::EnableKeyRepeat(true) 来确保。这意味着在按住某个键时它将重复发送 KeyPressed 事件。

尝试在主事件循环之外使用基于查询的方法,看看这是否适合您。

I know this is an old question but I would like to answer it in the interest of helping others who may find themselves here experiencing similiar problems.

SFML 1.6 has two ways you can get input from the user. One is event-based where you process each event sent to you via sf::Window::GetEvent(). The other is query-based where you check the sf::Input class of your window directly.

You have used the query-based method here but put it inside an event loop which isn't really the way it was intended to be used. It was meant to be used like this. This is a nice feature because SFML essentially keeps a boolean table of keys automatically for you so you don't need to manage key states yourself. IMHO for using repeating input this is more elegant since you won't be spamming your event queue, just checking a boolean value.

while(app.GetEvent(event))
    if(event.Type == sf::Event::Closed) running=false;
    if(event.Type == sf::Event::KeyPressed && event.Key.Code == sf::Key::Right)
    {
      // move right
    }
}

If you wanted to just query sf::Input directly then you use the same code as above, but you put it outside the event loop.

while(app.GetEvent(event)
{
}

if (myWindow.GetInput().IsKeyDown(sf::Key::Right))
{
}

By default automatic key repeat should be enabled for sf::Windows but you can make sure by using sf::Window::EnableKeyRepeat(true). This means it will send a KeyPressed event repeatedly while a key is held down.

Try using the query-based method outside the main event loop and see if that works for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文