重复关键事件阻止

时间:2011-03-07 12:12:17

标签: events key blocking sfml

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

它在我测试过的所有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
}

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

1 个答案:

答案 0 :(得分:3)

我知道这是一个老问题,但我想回答这个问题是为了帮助那些可能会发现自己遇到类似问题的人。

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事件。

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