【问题标题】:Handling input events in a MetalKit application在 MetalKit 应用程序中处理输入事件
【发布时间】:2016-03-31 02:56:57
【问题描述】:

我在 Xcode 中使用使用 MetalKit 的“游戏”模板在 OS X 上创建了一个应用程序。如何处理 keyDown 和 keyUp 等输入事件?我尝试添加

- (void)keyDown:(NSEvent *)theEvent
{
    NSLog( @"Key down\n" );
}

- (void)keyUp:(NSEvent *)theEvent
{
    NSLog( @"Key up\n" );
}

进入 AppDelegate 和 GameViewController 但当我按下一个键时它们不会被调用。

【问题讨论】:

    标签: objective-c macos input metal metalkit


    【解决方案1】:

    对于 Swift 应用,将这些添加到您的 MTKView 子类中:

    // yes, this MUST be here.
    override var acceptsFirstResponder: Bool { 
        return true 
    }
    override func keyDown(with theEvent: NSEvent) {
        // do something 
    }
    override func keyUp(with theEvent: NSEvent) {
        // do something 
    }
    

    【讨论】:

    • 这是正确答案,在 macOS Big Sur 11.3.1 (20E241) + Xcode Version 12.5 (12E262) 上测试。
    【解决方案2】:

    如果您不使用MetalKit,则需要创建一个作为NSView 子类的视图并在其中实现以下方法:

    - (void)keyDown:(NSEvent *)theEvent
    {
        NSLog(@"onKeyDown Detected; Merry Christmas, by the way.");
    }
    
    - (BOOL)acceptsFirstResponder
    {
        return YES;
    }
    

    但是,如果您使用的是MetalKit,您也可以这样做,并在一个子类化MTKView 的视图中实现上述方法。

    我在两个版本上都进行了测试; keyDown 在按键被按下时被调用。

    【讨论】:

    • 是的。如果您习惯于 iOS 开发,您可能会对此感到惊讶——在 OS X 中,视图控制器不像在 iOS 中那样属于responder chain。为了接收关键事件,视图需要成为第一响应者。
    • 我遇到了同样的问题,尝试了同样的解决方法,并且确实子类化 MTKView 解决了它。现在我有一个谜题;见鬼,摆脱了子类,恢复到原来的 MTKView 但现在 GameViewController 中的“keyDown”可以工作了!而且我不会在任何地方覆盖“acceptsFirstResponder”!
    • ...同样神秘的是,经过 10 个小时和多次编译+运行后,它停止了工作。 Xcode gremlins 毫无疑问。
    【解决方案3】:

    如上所述:您必须继承 MTKView 并在子类中处理 keyDown。 还要记住将 Storyboard 中的视图类从 MTKView 设置为子类。

    这是消除 MTKView 中那些讨厌的哔哔声的方法(由于未处理的 keyDown)。

    但也如 cmets 中所述:如果您将 Storyboard 中的类重置为 MTKView,keyDown 将继续被处理(并且没有哔声)。奇怪。

    如果没有按照其中一个答案的建议进行子类化,我从来没有让它工作。在那个阶段如何获得指向 GameViewController 的指针?

    【讨论】:

      【解决方案4】:

      这是我在 MetalKit 应用程序中获得键盘输入的方法,而无需子类化 MTKView

      我在 GameViewController.mm 中实现了keyDown

      - (void)keyDown:(NSEvent *)theEvent
      {
          NSLog(@"keyDown Detected");
      }
      
      - (BOOL)acceptsFirstResponder
      {
          return YES;
      }
      

      在我的 AppDelegate.m 中,我在 applicationDidFinishLaunching 中调用 [[ [myViewController view] window ] makeFirstResponder:myViewController];,其中 myViewController 指向我的 GameViewController 实例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多