【问题标题】:Repeating key events blocking重复关键事件阻塞
【发布时间】:2011-03-07 12:12:17
【问题描述】:

我用 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
}

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

【问题讨论】:

  • 您是否尝试过将键状态存储在布尔值中,然后根据布尔值进行逻辑处理?所以 。 . . . . if(input.IsKeyDown(sf::Key::Right)) 正确 = true; . . . . . . if(right) moveRight();

标签: events key blocking sfml


【解决方案1】:

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

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

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

【讨论】:

  • 到此结束,sf::Window::EnableKeyRepeat(true) 刚刚回答了我的问题。谢谢你的详细信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多